four-flap-meme-sdk 3.0.0 → 4.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 (446) hide show
  1. package/dist/bundle/four-meme/approve-tokenmanager.d.ts +2 -2
  2. package/dist/bundle/four-meme/approve-tokenmanager.js +3 -3
  3. package/dist/bundle/four-meme/core/buy-flow.d.ts +5 -0
  4. package/dist/bundle/four-meme/core/buy-flow.js +147 -0
  5. package/dist/bundle/four-meme/core/constants.d.ts +6 -0
  6. package/dist/bundle/four-meme/core/constants.js +15 -0
  7. package/dist/bundle/four-meme/core/create-token.d.ts +5 -0
  8. package/dist/bundle/four-meme/core/create-token.js +137 -0
  9. package/dist/bundle/four-meme/core/index.d.ts +14 -0
  10. package/dist/bundle/four-meme/core/index.js +14 -0
  11. package/dist/bundle/four-meme/core/sell-flow.d.ts +5 -0
  12. package/dist/bundle/four-meme/core/sell-flow.js +240 -0
  13. package/dist/bundle/four-meme/core-helpers.js +1 -1
  14. package/dist/bundle/four-meme/core.d.ts +7 -4
  15. package/dist/bundle/four-meme/core.js +5 -513
  16. package/dist/bundle/four-meme/pancake-proxy/approve.d.ts +15 -0
  17. package/dist/bundle/four-meme/pancake-proxy/approve.js +113 -0
  18. package/dist/bundle/four-meme/pancake-proxy/buy.d.ts +8 -0
  19. package/dist/bundle/four-meme/pancake-proxy/buy.js +143 -0
  20. package/dist/bundle/four-meme/pancake-proxy/constants.d.ts +25 -0
  21. package/dist/bundle/four-meme/pancake-proxy/constants.js +14 -0
  22. package/dist/bundle/four-meme/pancake-proxy/helpers.d.ts +45 -0
  23. package/dist/bundle/four-meme/pancake-proxy/helpers.js +232 -0
  24. package/dist/bundle/four-meme/pancake-proxy/index.d.ts +15 -0
  25. package/dist/bundle/four-meme/pancake-proxy/index.js +15 -0
  26. package/dist/bundle/four-meme/pancake-proxy/sell.d.ts +8 -0
  27. package/dist/bundle/four-meme/pancake-proxy/sell.js +194 -0
  28. package/dist/bundle/four-meme/pancake-proxy.d.ts +4 -20
  29. package/dist/bundle/four-meme/pancake-proxy.js +3 -670
  30. package/dist/bundle/four-meme/private/buy.d.ts +16 -0
  31. package/dist/bundle/four-meme/private/buy.js +225 -0
  32. package/dist/bundle/four-meme/private/index.d.ts +11 -0
  33. package/dist/bundle/four-meme/private/index.js +11 -0
  34. package/dist/bundle/four-meme/private/sell.d.ts +18 -0
  35. package/dist/bundle/four-meme/private/sell.js +245 -0
  36. package/dist/bundle/four-meme/private.d.ts +5 -25
  37. package/dist/bundle/four-meme/private.js +5 -463
  38. package/dist/bundle/four-meme/swap/batch.d.ts +8 -0
  39. package/dist/bundle/four-meme/swap/batch.js +170 -0
  40. package/dist/bundle/four-meme/swap/bundle.d.ts +8 -0
  41. package/dist/bundle/four-meme/swap/bundle.js +147 -0
  42. package/dist/bundle/four-meme/swap/index.d.ts +14 -0
  43. package/dist/bundle/four-meme/swap/index.js +13 -0
  44. package/dist/bundle/four-meme/swap/quick-batch.d.ts +8 -0
  45. package/dist/bundle/four-meme/swap/quick-batch.js +206 -0
  46. package/dist/bundle/four-meme/swap-buy-first/helpers.d.ts +20 -0
  47. package/dist/bundle/four-meme/swap-buy-first/helpers.js +39 -0
  48. package/dist/bundle/four-meme/swap-buy-first/index.d.ts +12 -0
  49. package/dist/bundle/four-meme/swap-buy-first/index.js +11 -0
  50. package/dist/bundle/four-meme/swap-buy-first/multi-wallet.d.ts +20 -0
  51. package/dist/bundle/four-meme/swap-buy-first/multi-wallet.js +198 -0
  52. package/dist/bundle/four-meme/swap-buy-first/single.d.ts +7 -0
  53. package/dist/bundle/four-meme/swap-buy-first/single.js +232 -0
  54. package/dist/bundle/four-meme/swap-buy-first.d.ts +4 -3
  55. package/dist/bundle/four-meme/swap-buy-first.js +4 -451
  56. package/dist/bundle/four-meme/swap-hop-helpers.d.ts +2 -2
  57. package/dist/bundle/four-meme/swap-sign-helpers.d.ts +2 -2
  58. package/dist/bundle/four-meme/swap-sign-helpers.js +1 -1
  59. package/dist/bundle/four-meme/swap.d.ts +4 -14
  60. package/dist/bundle/four-meme/swap.js +4 -502
  61. package/dist/bundle/four-meme/types/index.d.ts +1 -1
  62. package/dist/bundle/four-meme/utils-disperse.d.ts +1 -1
  63. package/dist/bundle/four-meme/utils-disperse.js +1 -1
  64. package/dist/bundle/four-meme/utils-pairwise.d.ts +1 -1
  65. package/dist/bundle/four-meme/utils-pairwise.js +1 -1
  66. package/dist/bundle/four-meme/utils-sweep/context.d.ts +39 -0
  67. package/dist/bundle/four-meme/utils-sweep/context.js +7 -0
  68. package/dist/bundle/four-meme/utils-sweep/erc20-no-hop.d.ts +5 -0
  69. package/dist/bundle/four-meme/utils-sweep/erc20-no-hop.js +162 -0
  70. package/dist/bundle/four-meme/utils-sweep/index.d.ts +13 -0
  71. package/dist/bundle/four-meme/utils-sweep/index.js +13 -0
  72. package/dist/bundle/four-meme/utils-sweep/main.d.ts +8 -0
  73. package/dist/bundle/four-meme/utils-sweep/main.js +114 -0
  74. package/dist/bundle/four-meme/utils-sweep/native-no-hop.d.ts +5 -0
  75. package/dist/bundle/four-meme/utils-sweep/native-no-hop.js +156 -0
  76. package/dist/bundle/four-meme/utils-sweep/with-hops.d.ts +6 -0
  77. package/dist/bundle/four-meme/utils-sweep/with-hops.js +382 -0
  78. package/dist/bundle/four-meme/utils-sweep.d.ts +3 -4
  79. package/dist/bundle/four-meme/utils-sweep.js +3 -740
  80. package/dist/bundle/internal.d.ts +2 -2
  81. package/dist/bundle/sign-context-helpers.d.ts +1 -26
  82. package/dist/bundle/sign-context-helpers.js +1 -63
  83. package/dist/bundle/submit/blockrazor.d.ts +94 -0
  84. package/dist/bundle/submit/blockrazor.js +122 -0
  85. package/dist/bundle/submit/direct.d.ts +118 -0
  86. package/dist/bundle/submit/direct.js +484 -0
  87. package/dist/bundle/submit/helpers.d.ts +7 -0
  88. package/dist/bundle/submit/helpers.js +15 -0
  89. package/dist/bundle/submit/index.d.ts +14 -0
  90. package/dist/bundle/submit/index.js +14 -0
  91. package/dist/bundle/submit/merkle.d.ts +84 -0
  92. package/dist/bundle/submit/merkle.js +121 -0
  93. package/dist/bundle/submit.d.ts +3 -286
  94. package/dist/bundle/submit.js +3 -724
  95. package/dist/chains/bsc/four/types.d.ts +1 -1
  96. package/dist/chains/bsc/index.d.ts +1 -1
  97. package/dist/chains/bsc/index.js +2 -0
  98. package/dist/chains/bsc/pancake/bundle-buy-first-build.d.ts +25 -0
  99. package/dist/chains/bsc/pancake/bundle-buy-first-build.js +177 -0
  100. package/dist/chains/bsc/pancake/bundle-buy-first-constants.d.ts +30 -0
  101. package/dist/chains/bsc/pancake/bundle-buy-first-constants.js +24 -0
  102. package/dist/chains/bsc/pancake/bundle-buy-first-helpers.d.ts +11 -149
  103. package/dist/chains/bsc/pancake/bundle-buy-first-helpers.js +12 -74
  104. package/dist/chains/bsc/pancake/bundle-buy-first-multi-wallet.d.ts +9 -0
  105. package/dist/chains/bsc/pancake/bundle-buy-first-multi-wallet.js +225 -0
  106. package/dist/chains/bsc/pancake/bundle-buy-first-plan.d.ts +14 -0
  107. package/dist/chains/bsc/pancake/bundle-buy-first-plan.js +64 -0
  108. package/dist/chains/bsc/pancake/bundle-buy-first-profit.d.ts +12 -0
  109. package/dist/chains/bsc/pancake/bundle-buy-first-profit.js +22 -0
  110. package/dist/chains/bsc/pancake/bundle-buy-first-quote.d.ts +15 -0
  111. package/dist/chains/bsc/pancake/bundle-buy-first-quote.js +122 -0
  112. package/dist/chains/bsc/pancake/bundle-buy-first-types.d.ts +179 -0
  113. package/dist/chains/bsc/pancake/bundle-buy-first-types.js +1 -0
  114. package/dist/chains/bsc/pancake/bundle-buy-first-validate.d.ts +2 -0
  115. package/dist/chains/bsc/pancake/bundle-buy-first-validate.js +41 -0
  116. package/dist/chains/bsc/pancake/bundle-buy-first.d.ts +1 -1
  117. package/dist/chains/bsc/pancake/bundle-buy-first.js +8 -578
  118. package/dist/chains/bsc/pancake/bundle-swap-helpers.d.ts +11 -239
  119. package/dist/chains/bsc/pancake/bundle-swap-helpers.js +12 -564
  120. package/dist/chains/bsc/pancake/bundle-swap-types.d.ts +183 -0
  121. package/dist/chains/bsc/pancake/bundle-swap-types.js +17 -0
  122. package/dist/chains/bsc/pancake/bundle-swap.d.ts +10 -132
  123. package/dist/chains/bsc/pancake/bundle-swap.js +12 -1003
  124. package/dist/chains/bsc/pancake/hop-chain.d.ts +18 -0
  125. package/dist/chains/bsc/pancake/hop-chain.js +227 -0
  126. package/dist/chains/bsc/pancake/quote.d.ts +14 -0
  127. package/dist/chains/bsc/pancake/quote.js +84 -0
  128. package/dist/chains/bsc/pancake/swap-batch.d.ts +42 -0
  129. package/dist/chains/bsc/pancake/swap-batch.js +283 -0
  130. package/dist/chains/bsc/pancake/swap-build.d.ts +19 -0
  131. package/dist/chains/bsc/pancake/swap-build.js +226 -0
  132. package/dist/chains/bsc/pancake/swap-cross.d.ts +42 -0
  133. package/dist/chains/bsc/pancake/swap-cross.js +140 -0
  134. package/dist/chains/bsc/pancake/swap-quick.d.ts +54 -0
  135. package/dist/chains/bsc/pancake/swap-quick.js +424 -0
  136. package/dist/chains/bsc/pancake/swap-single.d.ts +2 -0
  137. package/dist/chains/bsc/pancake/swap-single.js +182 -0
  138. package/dist/chains/bsc/platforms/four/index.d.ts +21 -3
  139. package/dist/chains/bsc/platforms/four/index.js +28 -3
  140. package/dist/chains/eni/batch-router/transfer-disperse.d.ts +37 -0
  141. package/dist/chains/eni/batch-router/transfer-disperse.js +302 -0
  142. package/dist/chains/eni/batch-router/transfer-shared.d.ts +9 -0
  143. package/dist/chains/eni/batch-router/transfer-shared.js +10 -0
  144. package/dist/chains/eni/batch-router/transfer-sweep.d.ts +51 -0
  145. package/dist/chains/eni/batch-router/transfer-sweep.js +364 -0
  146. package/dist/chains/eni/batch-router/transfer.d.ts +4 -74
  147. package/dist/chains/eni/batch-router/transfer.js +2 -647
  148. package/dist/chains/eni/index.d.ts +2 -0
  149. package/dist/chains/eni/index.js +4 -0
  150. package/dist/chains/eni/platforms/daoaas/portal-direct-profit.d.ts +17 -0
  151. package/dist/chains/eni/platforms/daoaas/portal-direct-profit.js +30 -0
  152. package/dist/chains/eni/platforms/daoaas/portal-direct-submit.d.ts +12 -0
  153. package/dist/chains/eni/platforms/daoaas/portal-direct-submit.js +396 -0
  154. package/dist/chains/eni/platforms/daoaas/portal-direct-tx.d.ts +20 -0
  155. package/dist/chains/eni/platforms/daoaas/portal-direct-tx.js +165 -0
  156. package/dist/chains/eni/platforms/daoaas/portal-direct.d.ts +3 -32
  157. package/dist/chains/eni/platforms/daoaas/portal-direct.js +3 -571
  158. package/dist/chains/eni/submit.js +1 -1
  159. package/dist/chains/xlayer/constants.d.ts +0 -2
  160. package/dist/chains/xlayer/constants.js +0 -2
  161. package/dist/chains/xlayer/eip7702/auth.d.ts +16 -0
  162. package/dist/chains/xlayer/eip7702/auth.js +81 -0
  163. package/dist/chains/xlayer/eip7702/bundle-create-buy.d.ts +22 -0
  164. package/dist/chains/xlayer/eip7702/bundle-create-buy.js +201 -0
  165. package/dist/chains/xlayer/eip7702/bundle-create-helpers.d.ts +114 -0
  166. package/dist/chains/xlayer/eip7702/bundle-create-helpers.js +139 -0
  167. package/dist/chains/xlayer/eip7702/bundle-create-to-dex.d.ts +24 -0
  168. package/dist/chains/xlayer/eip7702/bundle-create-to-dex.js +233 -0
  169. package/dist/chains/xlayer/eip7702/bundle-create.d.ts +3 -35
  170. package/dist/chains/xlayer/eip7702/bundle-create.js +3 -746
  171. package/dist/chains/xlayer/eip7702/bundle-graduate-buy.d.ts +22 -0
  172. package/dist/chains/xlayer/eip7702/bundle-graduate-buy.js +214 -0
  173. package/dist/chains/xlayer/eip7702/bundle-sell.js +1 -1
  174. package/dist/chains/xlayer/eip7702/bundle-swap-batch.d.ts +31 -0
  175. package/dist/chains/xlayer/eip7702/bundle-swap-batch.js +216 -0
  176. package/dist/chains/xlayer/eip7702/bundle-swap-helpers.d.ts +21 -0
  177. package/dist/chains/xlayer/eip7702/bundle-swap-helpers.js +206 -0
  178. package/dist/chains/xlayer/eip7702/bundle-swap-multi.d.ts +33 -0
  179. package/dist/chains/xlayer/eip7702/bundle-swap-multi.js +146 -0
  180. package/dist/chains/xlayer/eip7702/bundle-swap-single.d.ts +31 -0
  181. package/dist/chains/xlayer/eip7702/bundle-swap-single.js +177 -0
  182. package/dist/chains/xlayer/eip7702/bundle-swap.d.ts +6 -61
  183. package/dist/chains/xlayer/eip7702/bundle-swap.js +3 -712
  184. package/dist/chains/xlayer/eip7702/bytes.d.ts +4 -0
  185. package/dist/chains/xlayer/eip7702/bytes.js +31 -0
  186. package/dist/chains/xlayer/eip7702/gas.d.ts +19 -0
  187. package/dist/chains/xlayer/eip7702/gas.js +152 -0
  188. package/dist/chains/xlayer/eip7702/multi-hop-transfer-disperse.d.ts +5 -0
  189. package/dist/chains/xlayer/eip7702/multi-hop-transfer-disperse.js +196 -0
  190. package/dist/chains/xlayer/eip7702/multi-hop-transfer-pairwise.d.ts +5 -0
  191. package/dist/chains/xlayer/eip7702/multi-hop-transfer-pairwise.js +188 -0
  192. package/dist/chains/xlayer/eip7702/multi-hop-transfer-sweep.d.ts +5 -0
  193. package/dist/chains/xlayer/eip7702/multi-hop-transfer-sweep.js +220 -0
  194. package/dist/chains/xlayer/eip7702/multi-hop-transfer.d.ts +8 -4
  195. package/dist/chains/xlayer/eip7702/multi-hop-transfer.js +5 -591
  196. package/dist/chains/xlayer/eip7702/profit.d.ts +32 -0
  197. package/dist/chains/xlayer/eip7702/profit.js +59 -0
  198. package/dist/chains/xlayer/eip7702/provider.d.ts +3 -0
  199. package/dist/chains/xlayer/eip7702/provider.js +17 -0
  200. package/dist/chains/xlayer/eip7702/time.d.ts +2 -0
  201. package/dist/chains/xlayer/eip7702/time.js +10 -0
  202. package/dist/chains/xlayer/eip7702/tx-build.d.ts +10 -0
  203. package/dist/chains/xlayer/eip7702/tx-build.js +128 -0
  204. package/dist/chains/xlayer/eip7702/utils.d.ts +19 -85
  205. package/dist/chains/xlayer/eip7702/utils.js +19 -484
  206. package/dist/chains/xlayer/eip7702/volume-bundle.d.ts +13 -0
  207. package/dist/chains/xlayer/eip7702/volume-bundle.js +250 -0
  208. package/dist/chains/xlayer/eip7702/volume-internal.d.ts +13 -0
  209. package/dist/chains/xlayer/eip7702/volume-internal.js +169 -0
  210. package/dist/chains/xlayer/eip7702/volume-make.d.ts +8 -0
  211. package/dist/chains/xlayer/eip7702/volume-make.js +38 -0
  212. package/dist/chains/xlayer/eip7702/volume-single-round.d.ts +17 -0
  213. package/dist/chains/xlayer/eip7702/volume-single-round.js +44 -0
  214. package/dist/chains/xlayer/eip7702/volume-swap.d.ts +18 -0
  215. package/dist/chains/xlayer/eip7702/volume-swap.js +30 -0
  216. package/dist/chains/xlayer/eip7702/volume-wash.d.ts +8 -0
  217. package/dist/chains/xlayer/eip7702/volume-wash.js +191 -0
  218. package/dist/chains/xlayer/eip7702/volume.d.ts +7 -35
  219. package/dist/chains/xlayer/eip7702/volume.js +5 -697
  220. package/dist/chains/xlayer/eip7702/wallet.d.ts +6 -0
  221. package/dist/chains/xlayer/eip7702/wallet.js +17 -0
  222. package/dist/chains/xlayer/eoa/aa-types.d.ts +176 -0
  223. package/dist/chains/xlayer/eoa/aa-types.js +6 -0
  224. package/dist/chains/xlayer/eoa/constants.d.ts +0 -2
  225. package/dist/chains/xlayer/eoa/constants.js +0 -2
  226. package/dist/chains/xlayer/eoa/context.d.ts +8 -0
  227. package/dist/chains/xlayer/eoa/context.js +23 -0
  228. package/dist/chains/xlayer/eoa/encoders.d.ts +147 -0
  229. package/dist/chains/xlayer/eoa/encoders.js +147 -0
  230. package/dist/chains/xlayer/eoa/eoa-bundle-swap-cross.d.ts +5 -0
  231. package/dist/chains/xlayer/eoa/eoa-bundle-swap-cross.js +113 -0
  232. package/dist/chains/xlayer/eoa/eoa-bundle-swap-helpers.d.ts +10 -123
  233. package/dist/chains/xlayer/eoa/eoa-bundle-swap-helpers.js +10 -225
  234. package/dist/chains/xlayer/eoa/eoa-bundle-swap-pure.d.ts +50 -0
  235. package/dist/chains/xlayer/eoa/eoa-bundle-swap-pure.js +170 -0
  236. package/dist/chains/xlayer/eoa/eoa-bundle-swap-quick.d.ts +5 -0
  237. package/dist/chains/xlayer/eoa/eoa-bundle-swap-quick.js +257 -0
  238. package/dist/chains/xlayer/eoa/eoa-bundle-swap-types.d.ts +99 -0
  239. package/dist/chains/xlayer/eoa/eoa-bundle-swap-types.js +11 -0
  240. package/dist/chains/xlayer/eoa/eoa-bundle-swap.d.ts +5 -47
  241. package/dist/chains/xlayer/eoa/eoa-bundle-swap.js +3 -522
  242. package/dist/chains/xlayer/eoa/eoa-types.d.ts +776 -0
  243. package/dist/chains/xlayer/eoa/eoa-types.js +6 -0
  244. package/dist/chains/xlayer/eoa/eoa-wash-volume.d.ts +8 -0
  245. package/dist/chains/xlayer/eoa/eoa-wash-volume.js +8 -0
  246. package/dist/chains/xlayer/eoa/format.d.ts +34 -0
  247. package/dist/chains/xlayer/eoa/format.js +56 -0
  248. package/dist/chains/xlayer/eoa/hop-chain.d.ts +4 -0
  249. package/dist/chains/xlayer/eoa/hop-chain.js +87 -0
  250. package/dist/chains/xlayer/eoa/nonce-map.d.ts +20 -0
  251. package/dist/chains/xlayer/eoa/nonce-map.js +51 -0
  252. package/dist/chains/xlayer/eoa/portal-ops.d.ts +9 -292
  253. package/dist/chains/xlayer/eoa/portal-ops.js +9 -486
  254. package/dist/chains/xlayer/eoa/query.d.ts +117 -0
  255. package/dist/chains/xlayer/eoa/query.js +285 -0
  256. package/dist/chains/xlayer/eoa/quote.d.ts +6 -0
  257. package/dist/chains/xlayer/eoa/quote.js +90 -0
  258. package/dist/chains/xlayer/eoa/types.d.ts +9 -959
  259. package/dist/chains/xlayer/eoa/types.js +9 -49
  260. package/dist/core/clients/blockrazor.js +1 -1
  261. package/dist/core/clients/merkle.js +1 -1
  262. package/dist/core/erc20/allowances.d.ts +104 -0
  263. package/dist/core/erc20/allowances.js +205 -0
  264. package/dist/core/erc20/approve.d.ts +141 -0
  265. package/dist/core/erc20/approve.js +325 -0
  266. package/dist/core/erc20/helpers.d.ts +20 -0
  267. package/dist/core/erc20/helpers.js +109 -0
  268. package/dist/core/erc20/index.d.ts +13 -0
  269. package/dist/core/erc20/index.js +12 -0
  270. package/dist/core/gas/bundle-gas.d.ts +6 -1
  271. package/dist/core/index.d.ts +1 -1
  272. package/dist/core/index.js +1 -1
  273. package/dist/core/quote/index.d.ts +1 -0
  274. package/dist/core/quote/index.js +1 -0
  275. package/dist/core/quote/quote-helpers.d.ts +78 -0
  276. package/dist/core/quote/quote-helpers.js +289 -0
  277. package/dist/core/quote/types.d.ts +1 -0
  278. package/dist/core/quote/types.js +1 -0
  279. package/dist/core/sign-context-helpers.d.ts +29 -0
  280. package/dist/core/sign-context-helpers.js +63 -0
  281. package/dist/domains/dex/direct-router-helpers.d.ts +16 -268
  282. package/dist/domains/dex/direct-router-helpers.js +16 -535
  283. package/dist/domains/dex/direct-router-types.d.ts +104 -0
  284. package/dist/domains/dex/direct-router-types.js +81 -0
  285. package/dist/domains/dex/direct-router-v2-buy.d.ts +2 -0
  286. package/dist/domains/dex/direct-router-v2-buy.js +249 -0
  287. package/dist/domains/dex/direct-router-v2-sell.d.ts +5 -0
  288. package/dist/domains/dex/direct-router-v2-sell.js +270 -0
  289. package/dist/domains/dex/direct-router-v2.d.ts +9 -0
  290. package/dist/domains/dex/direct-router-v2.js +9 -0
  291. package/dist/domains/dex/direct-router-v3.d.ts +17 -0
  292. package/dist/domains/dex/direct-router-v3.js +432 -0
  293. package/dist/domains/dex/direct-router.d.ts +11 -26
  294. package/dist/domains/dex/direct-router.js +10 -977
  295. package/dist/domains/dex/dyo-encode.d.ts +62 -0
  296. package/dist/domains/dex/dyo-encode.js +124 -0
  297. package/dist/domains/dex/profit.d.ts +24 -0
  298. package/dist/domains/dex/profit.js +86 -0
  299. package/dist/domains/dex/provider.d.ts +10 -0
  300. package/dist/domains/dex/provider.js +27 -0
  301. package/dist/domains/dex/quote.d.ts +7 -0
  302. package/dist/domains/dex/quote.js +52 -0
  303. package/dist/domains/dex/router.d.ts +56 -0
  304. package/dist/domains/dex/router.js +193 -0
  305. package/dist/domains/flap/portal-bundle/batch.d.ts +9 -0
  306. package/dist/domains/flap/portal-bundle/batch.js +193 -0
  307. package/dist/domains/flap/portal-bundle/create.d.ts +5 -0
  308. package/dist/domains/flap/portal-bundle/create.js +153 -0
  309. package/dist/domains/flap/portal-bundle/helpers.d.ts +32 -0
  310. package/dist/domains/flap/portal-bundle/helpers.js +50 -0
  311. package/dist/domains/flap/portal-bundle/index.d.ts +16 -0
  312. package/dist/domains/flap/portal-bundle/index.js +15 -0
  313. package/dist/domains/flap/portal-bundle/private.d.ts +5 -0
  314. package/dist/domains/flap/portal-bundle/private.js +198 -0
  315. package/dist/domains/flap/portal-bundle/types.d.ts +102 -0
  316. package/dist/domains/flap/portal-bundle/types.js +1 -0
  317. package/dist/domains/flap/portal-bundle-merkle/core-batch.d.ts +13 -0
  318. package/dist/domains/flap/portal-bundle-merkle/core-batch.js +376 -0
  319. package/dist/domains/flap/portal-bundle-merkle/core-helpers.d.ts +75 -7
  320. package/dist/domains/flap/portal-bundle-merkle/core-helpers.js +259 -20
  321. package/dist/domains/flap/portal-bundle-merkle/core.d.ts +2 -13
  322. package/dist/domains/flap/portal-bundle-merkle/core.js +12 -629
  323. package/dist/domains/flap/portal-bundle-merkle/create-to-dex/constants.d.ts +70 -0
  324. package/dist/domains/flap/portal-bundle-merkle/create-to-dex/constants.js +90 -0
  325. package/dist/domains/flap/portal-bundle-merkle/create-to-dex/index.d.ts +12 -0
  326. package/dist/domains/flap/portal-bundle-merkle/create-to-dex/index.js +11 -0
  327. package/dist/domains/flap/portal-bundle-merkle/create-to-dex/main.d.ts +15 -0
  328. package/dist/domains/flap/portal-bundle-merkle/create-to-dex/main.js +432 -0
  329. package/dist/domains/flap/portal-bundle-merkle/create-to-dex/types.d.ts +113 -0
  330. package/dist/domains/flap/portal-bundle-merkle/create-to-dex/types.js +4 -0
  331. package/dist/domains/flap/portal-bundle-merkle/create-to-dex.d.ts +4 -127
  332. package/dist/domains/flap/portal-bundle-merkle/create-to-dex.js +4 -527
  333. package/dist/domains/flap/portal-bundle-merkle/curve-to-dex/constants.d.ts +42 -0
  334. package/dist/domains/flap/portal-bundle-merkle/curve-to-dex/constants.js +81 -0
  335. package/dist/domains/flap/portal-bundle-merkle/curve-to-dex/index.d.ts +12 -0
  336. package/dist/domains/flap/portal-bundle-merkle/curve-to-dex/index.js +11 -0
  337. package/dist/domains/flap/portal-bundle-merkle/curve-to-dex/main.d.ts +15 -0
  338. package/dist/domains/flap/portal-bundle-merkle/curve-to-dex/main.js +339 -0
  339. package/dist/domains/flap/portal-bundle-merkle/curve-to-dex/types.d.ts +72 -0
  340. package/dist/domains/flap/portal-bundle-merkle/curve-to-dex/types.js +4 -0
  341. package/dist/domains/flap/portal-bundle-merkle/curve-to-dex.d.ts +4 -85
  342. package/dist/domains/flap/portal-bundle-merkle/curve-to-dex.js +4 -425
  343. package/dist/domains/flap/portal-bundle-merkle/pancake-proxy/approve.d.ts +12 -0
  344. package/dist/domains/flap/portal-bundle-merkle/pancake-proxy/approve.js +102 -0
  345. package/dist/domains/flap/portal-bundle-merkle/pancake-proxy/buy.d.ts +5 -0
  346. package/dist/domains/flap/portal-bundle-merkle/pancake-proxy/buy.js +135 -0
  347. package/dist/domains/flap/portal-bundle-merkle/pancake-proxy/helpers.d.ts +52 -0
  348. package/dist/domains/flap/portal-bundle-merkle/pancake-proxy/helpers.js +267 -0
  349. package/dist/domains/flap/portal-bundle-merkle/pancake-proxy/index.d.ts +14 -0
  350. package/dist/domains/flap/portal-bundle-merkle/pancake-proxy/index.js +14 -0
  351. package/dist/domains/flap/portal-bundle-merkle/pancake-proxy/sell.d.ts +5 -0
  352. package/dist/domains/flap/portal-bundle-merkle/pancake-proxy/sell.js +195 -0
  353. package/dist/domains/flap/portal-bundle-merkle/pancake-proxy.d.ts +3 -24
  354. package/dist/domains/flap/portal-bundle-merkle/pancake-proxy.js +3 -700
  355. package/dist/domains/flap/portal-bundle-merkle/private/buy.d.ts +9 -0
  356. package/dist/domains/flap/portal-bundle-merkle/private/buy.js +188 -0
  357. package/dist/domains/flap/portal-bundle-merkle/private/helpers.d.ts +36 -0
  358. package/dist/domains/flap/portal-bundle-merkle/private/helpers.js +127 -0
  359. package/dist/domains/flap/portal-bundle-merkle/private/index.d.ts +12 -0
  360. package/dist/domains/flap/portal-bundle-merkle/private/index.js +12 -0
  361. package/dist/domains/flap/portal-bundle-merkle/private/sell.d.ts +9 -0
  362. package/dist/domains/flap/portal-bundle-merkle/private/sell.js +191 -0
  363. package/dist/domains/flap/portal-bundle-merkle/private.d.ts +5 -15
  364. package/dist/domains/flap/portal-bundle-merkle/private.js +5 -494
  365. package/dist/domains/flap/portal-bundle-merkle/swap-batch.js +3 -2
  366. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-chain.d.ts +4 -0
  367. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-chain.js +43 -0
  368. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-constants.d.ts +13 -0
  369. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-constants.js +21 -0
  370. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-helpers.d.ts +11 -121
  371. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-helpers.js +11 -109
  372. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-multi-wallet.d.ts +20 -0
  373. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-multi-wallet.js +223 -0
  374. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-plan.d.ts +32 -0
  375. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-plan.js +66 -0
  376. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-profit.d.ts +22 -0
  377. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-profit.js +22 -0
  378. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-quote.d.ts +51 -0
  379. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-quote.js +149 -0
  380. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-types.d.ts +87 -0
  381. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first-types.js +1 -0
  382. package/dist/domains/flap/portal-bundle-merkle/swap-buy-first.js +5 -404
  383. package/dist/domains/flap/portal-bundle-merkle/swap-helpers.d.ts +0 -1
  384. package/dist/domains/flap/portal-bundle-merkle/swap-helpers.js +0 -7
  385. package/dist/domains/flap/portal-bundle-merkle/swap-planning.js +1 -1
  386. package/dist/domains/flap/portal-bundle-merkle/swap-quick-batch.js +3 -2
  387. package/dist/domains/flap/portal-bundle-merkle/swap-single.js +3 -2
  388. package/dist/domains/flap/portal-bundle-merkle/utils/disperse.d.ts +2 -0
  389. package/dist/domains/flap/portal-bundle-merkle/utils/disperse.js +275 -0
  390. package/dist/domains/flap/portal-bundle-merkle/utils/index.d.ts +11 -0
  391. package/dist/domains/flap/portal-bundle-merkle/utils/index.js +11 -0
  392. package/dist/domains/flap/portal-bundle-merkle/utils/sweep.d.ts +9 -0
  393. package/dist/domains/flap/portal-bundle-merkle/utils/sweep.js +570 -0
  394. package/dist/domains/flap/portal-bundle-merkle/utils.d.ts +5 -8
  395. package/dist/domains/flap/portal-bundle-merkle/utils.js +5 -841
  396. package/dist/domains/flap/portal-bundle.d.ts +5 -117
  397. package/dist/domains/flap/portal-bundle.js +5 -587
  398. package/dist/domains/flap/portal.d.ts +13 -404
  399. package/dist/domains/flap/portal.js +12 -619
  400. package/dist/domains/flap/reader.d.ts +51 -0
  401. package/dist/domains/flap/reader.js +275 -0
  402. package/dist/domains/flap/types.d.ts +246 -0
  403. package/dist/domains/flap/types.js +104 -0
  404. package/dist/domains/flap/vault/constants.d.ts +220 -0
  405. package/dist/domains/flap/vault/constants.js +173 -0
  406. package/dist/domains/flap/vault/encode.d.ts +39 -0
  407. package/dist/domains/flap/vault/encode.js +135 -0
  408. package/dist/domains/flap/vault/index.d.ts +15 -0
  409. package/dist/domains/flap/vault/index.js +14 -0
  410. package/dist/domains/flap/vault/query.d.ts +40 -0
  411. package/dist/domains/flap/vault/query.js +104 -0
  412. package/dist/domains/flap/vault/types.d.ts +147 -0
  413. package/dist/domains/flap/vault/types.js +29 -0
  414. package/dist/domains/flap/vault.d.ts +3 -413
  415. package/dist/domains/flap/vault.js +3 -467
  416. package/dist/domains/flap/writer.d.ts +124 -0
  417. package/dist/domains/flap/writer.js +255 -0
  418. package/dist/domains/four/contracts/tm-bundle-batch.d.ts +35 -0
  419. package/dist/domains/four/contracts/tm-bundle-batch.js +286 -0
  420. package/dist/domains/four/contracts/tm-bundle-create.d.ts +2 -0
  421. package/dist/domains/four/contracts/tm-bundle-create.js +304 -0
  422. package/dist/domains/four/contracts/tm-bundle-helpers.d.ts +2 -1
  423. package/dist/domains/four/contracts/tm-bundle-helpers.js +3 -0
  424. package/dist/domains/four/contracts/tm-bundle-private.d.ts +36 -0
  425. package/dist/domains/four/contracts/tm-bundle-private.js +164 -0
  426. package/dist/domains/four/contracts/tm-bundle.d.ts +10 -71
  427. package/dist/domains/four/contracts/tm-bundle.js +9 -738
  428. package/dist/domains/lp-inspect/inspect-helpers.d.ts +25 -0
  429. package/dist/domains/lp-inspect/inspect-helpers.js +343 -0
  430. package/dist/domains/lp-inspect/inspect.d.ts +8 -0
  431. package/dist/domains/lp-inspect/inspect.js +332 -0
  432. package/dist/domains/lp-inspect/lp-inspect.d.ts +9 -37
  433. package/dist/domains/lp-inspect/lp-inspect.js +9 -775
  434. package/dist/domains/lp-inspect/registry.d.ts +43 -0
  435. package/dist/domains/lp-inspect/registry.js +127 -0
  436. package/dist/domains/merkle/index.d.ts +1 -1
  437. package/dist/exports/root-bundle-and-tooling.d.ts +9 -1
  438. package/dist/exports/root-bundle-and-tooling.js +8 -1
  439. package/dist/exports/root-foundations.d.ts +1 -1
  440. package/dist/exports/root-foundations.js +1 -1
  441. package/dist/exports/root-swap-dex-and-xlayer.d.ts +4 -4
  442. package/dist/exports/root-swap-dex-and-xlayer.js +4 -4
  443. package/dist/index.d.ts +1 -1
  444. package/dist/index.js +1 -1
  445. package/dist/utils/swap-helpers.js +1 -1
  446. package/package.json +1 -81
@@ -1,979 +1,12 @@
1
1
  /**
2
- * direct-router - 主函数
3
- */
4
- import { ethers, Wallet, Contract } from 'ethers';
5
- import { NonceManager, buildProfitHopTransactions, PROFIT_HOP_COUNT, buildGasFields } from '../../utils/bundle-helpers.js';
6
- import { getProfitRecipient, CHAINS } from '../../core/constants/index.js';
7
- import { GAS_LIMITS } from '../../core/constants/index.js';
8
- import { getErrorMessageFromUnknown } from '../../core/index.js';
9
- import { ERC20_ABI } from '../../abis/common.js';
10
- import { getTokenToNativeQuote, quoteV2 } from '../quote/quote-helpers.js';
11
- import { CHAIN_IDS, DIRECT_ROUTERS, SWAP_ROUTER02_V2_ABI, V2_ROUTER_ABI, V3_ROUTER02_ABI, V3_ROUTER_LEGACY_ABI, buildBribeTransaction, buildProfitTransactionWithHops, calculateProfitAmount, encodeDYORMulticall, encodeDYORRefundETH, encodeDYORSwapExactTokensForTokens, encodeDYORUnwrapWETH9, findMaxFlowIndex, filterEniNativeBuyIndices, getBribeAmount, getCachedProvider, getDeadline, getGasLimit, getGasPrice, getWrappedNative, isDYORSwap, isLegacySwapRouter, isNativeToken, isSwapRouter02, quoteXLayerV3TokenToNativeBySlot0, truncateDecimals, } from './direct-router-helpers.js';
12
- export { DIRECT_ROUTERS } from './direct-router-helpers.js';
13
- export async function directV2BatchBuy(params) {
14
- const { chain, privateKeys, buyAmounts, tokenAddress, routerAddress, quoteToken, quoteTokenDecimals = 18, startNonces, config, } = params;
15
- if (privateKeys.length !== buyAmounts.length) {
16
- throw new Error('privateKeys 和 buyAmounts 长度必须相同');
17
- }
18
- const chainId = config.chainId || CHAIN_IDS[chain.toUpperCase()] || CHAINS.BSC.chainId;
19
- // ✅ 方案 C:使用缓存的 Provider
20
- const provider = getCachedProvider(config.rpcUrl, chainId, chain);
21
- const useNative = isNativeToken(quoteToken);
22
- const wrappedNative = getWrappedNative(chain);
23
- // 创建钱包
24
- const wallets = privateKeys.map((pk) => new Wallet(pk, provider));
25
- // ✅ 预先计算所有金额(同步操作,无 RPC)
26
- const flowAmounts = buyAmounts.map((amount) => ethers.parseUnits(amount, quoteTokenDecimals));
27
- const totalFlowWei = flowAmounts.reduce((sum, amt) => sum + amt, 0n);
28
- const baseProfitWei = calculateProfitAmount(totalFlowWei);
29
- // ✅ 方案 B:并行获取 nonces、gasPrice、ERC20 报价 以及(非原生代币时)授权额度
30
- const quoteTokenContract = !useNative && quoteToken ? new Contract(quoteToken, ERC20_ABI, provider) : null;
31
- const [nonces, gasPrice, nativeProfitWei, buyAllowances] = await Promise.all([
32
- startNonces && startNonces.length === wallets.length
33
- ? Promise.resolve(startNonces)
34
- : new NonceManager(provider).getNextNoncesForWallets(wallets),
35
- getGasPrice(provider, config),
36
- !useNative && baseProfitWei > 0n && quoteToken
37
- ? getTokenToNativeQuote(provider, quoteToken, baseProfitWei, chain, 'v2')
38
- : Promise.resolve(baseProfitWei),
39
- quoteTokenContract
40
- ? Promise.all(wallets.map((w) => quoteTokenContract.allowance(w.address, routerAddress).catch(() => 0n)))
41
- : Promise.resolve(wallets.map(() => ethers.MaxUint256)),
42
- ]);
43
- // 确定最终利润金额(ENI 链额外补偿利润转账的 gas 成本)
44
- let profitWei = nativeProfitWei > 0n ? nativeProfitWei : 0n;
45
- if (profitWei > 0n && chain.toUpperCase() === 'ENI') {
46
- profitWei += GAS_LIMITS.NATIVE_TRANSFER * gasPrice;
47
- }
48
- const gasLimit = getGasLimit(config, 250000);
49
- const txType = config.txType ?? 0;
50
- const deadline = getDeadline();
51
- // ENI 链原生代币买入:链上余额预检,跳过余额不足的钱包
52
- let activeIndices = null;
53
- if (useNative && chain.toUpperCase() === 'ENI') {
54
- const eniBalances = await Promise.all(wallets.map((w) => provider.getBalance(w.address)));
55
- activeIndices = filterEniNativeBuyIndices(eniBalances, flowAmounts, gasLimit, gasPrice, profitWei);
56
- }
57
- // 如果有钱包被跳过,重建数组(仅 ENI)
58
- let activeWallets = wallets;
59
- let activeFlowAmounts = flowAmounts;
60
- let activeNonces = nonces;
61
- let activeBuyAllowances = buyAllowances;
62
- if (activeIndices) {
63
- activeWallets = activeIndices.map((i) => wallets[i]);
64
- activeFlowAmounts = activeIndices.map((i) => flowAmounts[i]);
65
- activeNonces = activeIndices.map((i) => nonces[i]);
66
- activeBuyAllowances = activeIndices.map((i) => buyAllowances[i]);
67
- }
68
- const activeTotalFlowWei = activeFlowAmounts.reduce((sum, amt) => sum + amt, 0n);
69
- const activeBaseProfitWei = calculateProfitAmount(activeTotalFlowWei);
70
- let activeProfitWei = activeBaseProfitWei > 0n ? activeBaseProfitWei : 0n;
71
- if (activeProfitWei > 0n && chain.toUpperCase() === 'ENI') {
72
- activeProfitWei += GAS_LIMITS.NATIVE_TRANSFER * gasPrice;
73
- }
74
- if (!activeIndices) {
75
- activeProfitWei = profitWei;
76
- }
77
- // ✅ 自动授权:ERC20 报价代币买入时,检查钱包对 Router 的授权额度,不足则插入 approve
78
- const buyApproveTxs = [];
79
- if (!useNative && quoteTokenContract) {
80
- for (let i = 0; i < activeWallets.length; i++) {
81
- if (activeFlowAmounts[i] <= 0n)
82
- continue;
83
- if (activeBuyAllowances[i] < activeFlowAmounts[i]) {
84
- const approveData = quoteTokenContract.interface.encodeFunctionData('approve', [
85
- routerAddress,
86
- ethers.MaxUint256,
87
- ]);
88
- const approveTx = await activeWallets[i].signTransaction({
89
- to: quoteToken,
90
- data: approveData,
91
- value: 0n,
92
- nonce: activeNonces[i],
93
- gasLimit: 60000n,
94
- ...buildGasFields(txType, gasPrice),
95
- chainId,
96
- });
97
- buyApproveTxs.push({ walletIndex: i, tx: approveTx });
98
- activeNonces[i]++;
99
- }
100
- }
101
- }
102
- // 构建路径
103
- const inputToken = useNative ? wrappedNative : quoteToken;
104
- const path = [inputToken, tokenAddress];
105
- // 判断 Router 类型
106
- const useSwapRouter02 = isSwapRouter02(chain, routerAddress);
107
- const useDYORSwap = isDYORSwap(chain, routerAddress);
108
- const routerIface = useSwapRouter02
109
- ? new ethers.Interface(SWAP_ROUTER02_V2_ABI)
110
- : new ethers.Interface(V2_ROUTER_ABI);
111
- // 构建交易数据的辅助函数
112
- const buildTxData = (wallet, amountWei) => {
113
- if (useDYORSwap) {
114
- const DYORSWAP_FACTORY = DIRECT_ROUTERS.XLAYER.DYORSWAP_FACTORY;
115
- const multicallData = [];
116
- multicallData.push(encodeDYORRefundETH(30));
117
- multicallData.push(encodeDYORSwapExactTokensForTokens(useNative ? 0n : amountWei, 0n, path, [], wallet.address, 1n, DYORSWAP_FACTORY));
118
- return { txData: encodeDYORMulticall(BigInt(deadline), multicallData), txValue: useNative ? amountWei : 0n };
119
- }
120
- else if (useSwapRouter02) {
121
- const swapData = routerIface.encodeFunctionData('swapExactTokensForTokens', [
122
- amountWei,
123
- 0n,
124
- path,
125
- wallet.address,
126
- ]);
127
- return {
128
- txData: routerIface.encodeFunctionData('multicall(uint256,bytes[])', [deadline, [swapData]]),
129
- txValue: useNative ? amountWei : 0n,
130
- };
131
- }
132
- else if (useNative) {
133
- return {
134
- txData: routerIface.encodeFunctionData('swapExactETHForTokensSupportingFeeOnTransferTokens', [
135
- 0n,
136
- path,
137
- wallet.address,
138
- deadline,
139
- ]),
140
- txValue: amountWei,
141
- };
142
- }
143
- else {
144
- return {
145
- txData: routerIface.encodeFunctionData('swapExactTokensForTokensSupportingFeeOnTransferTokens', [
146
- amountWei,
147
- 0n,
148
- path,
149
- wallet.address,
150
- deadline,
151
- ]),
152
- txValue: 0n,
153
- };
154
- }
155
- };
156
- // 选择金额最大的钱包支付贿赂和利润
157
- const maxFlowIndex = findMaxFlowIndex(activeFlowAmounts);
158
- // 计算贿赂金额(仅 BSC 链)
159
- const bribeWei = getBribeAmount(config, chain);
160
- const hasBribe = bribeWei > 0n && activeWallets.length > 0;
161
- const hasProfit = activeProfitWei > 0n;
162
- // 计算 nonce 偏移
163
- const nonceOffsets = activeWallets.map((_, i) => (i === maxFlowIndex && hasBribe ? 1 : 0));
164
- // ✅ 方案 A:并行签名所有交易(贿赂、主交易、利润)
165
- const signPromises = [];
166
- // 贿赂交易
167
- if (hasBribe) {
168
- signPromises.push(buildBribeTransaction(activeWallets[maxFlowIndex], bribeWei, activeNonces[maxFlowIndex], gasPrice, chainId, txType).then((tx) => ({ type: 'bribe', index: 0, tx })));
169
- }
170
- // 主交易(并行签名)
171
- activeWallets.forEach((wallet, i) => {
172
- const { txData, txValue } = buildTxData(wallet, activeFlowAmounts[i]);
173
- signPromises.push(wallet
174
- .signTransaction({
175
- to: routerAddress,
176
- data: txData,
177
- value: txValue,
178
- nonce: activeNonces[i] + nonceOffsets[i],
179
- gasLimit,
180
- ...buildGasFields(txType, gasPrice),
181
- chainId,
182
- })
183
- .then((tx) => ({ type: 'swap', index: i, tx })));
184
- });
185
- // ✅ 并行执行所有签名
186
- const signedResults = await Promise.all(signPromises);
187
- // 按类型分组并按顺序组装:approve → 贿赂 → 交易
188
- const approveSignedTxs = buyApproveTxs.sort((a, b) => a.walletIndex - b.walletIndex).map((a) => a.tx);
189
- const bribeTxs = signedResults.filter((r) => r.type === 'bribe').map((r) => r.tx);
190
- const swapTxs = signedResults
191
- .filter((r) => r.type === 'swap')
192
- .sort((a, b) => a.index - b.index)
193
- .map((r) => r.tx);
194
- const signedTxs = [...approveSignedTxs, ...bribeTxs, ...swapTxs];
195
- // ✅ 检查是否使用分布式利润模式
196
- const profitMode = config.profitMode || 'single';
197
- const skipProfit = config.skipProfit === true;
198
- const profitAddr = getProfitRecipient();
199
- // 利润多跳转账
200
- let profitHopWallets;
201
- if (hasProfit && !skipProfit) {
202
- if (profitMode === 'distributed') {
203
- // ✅ 分布式模式:每个钱包独立扣除自己的利润
204
- const MAX_DISTRIBUTED_WALLETS = 12;
205
- if (activeWallets.length > MAX_DISTRIBUTED_WALLETS) {
206
- throw new Error(`分布式利润模式最多支持 ${MAX_DISTRIBUTED_WALLETS} 个钱包,当前 ${activeWallets.length} 个`);
207
- }
208
- profitHopWallets = [];
209
- // 计算每个钱包的利润(按比例分配)
210
- for (let i = 0; i < activeWallets.length; i++) {
211
- const walletProfit = activeTotalFlowWei > 0n ? (activeProfitWei * activeFlowAmounts[i]) / activeTotalFlowWei : 0n;
212
- if (walletProfit > 0n) {
213
- const walletProfitNonce = activeNonces[i] + nonceOffsets[i] + 1;
214
- const profitResult = await buildProfitHopTransactions({
215
- provider,
216
- payerWallet: activeWallets[i],
217
- profitAmount: walletProfit,
218
- profitRecipient: profitAddr,
219
- hopCount: PROFIT_HOP_COUNT,
220
- gasPrice,
221
- chainId,
222
- txType,
223
- startNonce: walletProfitNonce,
224
- });
225
- signedTxs.push(...profitResult.signedTransactions);
226
- if (profitResult.hopWallets) {
227
- profitHopWallets.push(...profitResult.hopWallets);
228
- }
229
- }
230
- }
231
- }
232
- else {
233
- // ✅ 单一模式(默认):从金额最大的钱包统一扣除
234
- const profitNonce = activeNonces[maxFlowIndex] + nonceOffsets[maxFlowIndex] + 1;
235
- const profitResult = await buildProfitTransactionWithHops(provider, activeWallets[maxFlowIndex], activeProfitWei, profitNonce, gasPrice, chainId, txType, profitAddr);
236
- signedTxs.push(...profitResult.signedTransactions);
237
- profitHopWallets = profitResult.hopWallets;
238
- }
239
- }
240
- return {
241
- signedTransactions: signedTxs,
242
- profitHopWallets,
243
- metadata: {
244
- profitMode,
245
- profitAmount: ethers.formatEther(activeProfitWei),
246
- profitRecipient: profitAddr,
247
- totalFlow: ethers.formatUnits(activeTotalFlowWei, quoteTokenDecimals),
248
- },
249
- };
250
- }
251
- /**
252
- * V2 批量卖出(直接调用 Router)
253
- */
254
- export async function directV2BatchSell(params) {
255
- const { chain, privateKeys, sellPercentages, sellAmounts, tokenAddress, tokenDecimals: inputDecimals, routerAddress, quoteToken, startNonces, config, } = params;
256
- const chainId = config.chainId || CHAIN_IDS[chain.toUpperCase()] || CHAINS.BSC.chainId;
257
- // ✅ 方案 C:使用缓存的 Provider
258
- const provider = getCachedProvider(config.rpcUrl, chainId, chain);
259
- const useNativeOutput = isNativeToken(quoteToken);
260
- const wrappedNative = getWrappedNative(chain);
261
- // 创建钱包
262
- const wallets = privateKeys.map((pk) => new Wallet(pk, provider));
263
- const tokenContract = new Contract(tokenAddress, ERC20_ABI, provider);
264
- // ✅ 性能优化:并行获取所有独立的 RPC 数据(包括授权额度)
265
- const [fetchedDecimals, balances, allowances, nonces, gasPrice] = await Promise.all([
266
- inputDecimals !== undefined
267
- ? Promise.resolve(inputDecimals)
268
- : tokenContract
269
- .decimals()
270
- .then((d) => Number(d))
271
- .catch(() => 18),
272
- Promise.all(wallets.map((w) => tokenContract.balanceOf(w.address))),
273
- Promise.all(wallets.map((w) => tokenContract.allowance(w.address, routerAddress).catch(() => 0n))),
274
- startNonces && startNonces.length === wallets.length
275
- ? Promise.resolve(startNonces)
276
- : new NonceManager(provider).getNextNoncesForWallets(wallets),
277
- getGasPrice(provider, config),
278
- ]);
279
- const tokenDecimals = fetchedDecimals;
280
- const gasLimit = getGasLimit(config, 300000);
281
- const txType = config.txType ?? 0;
282
- const deadline = getDeadline();
283
- // 计算卖出数量(同步操作,无 RPC),并安全兜底不超过链上实际余额
284
- const sellAmountsWei = [];
285
- for (let i = 0; i < wallets.length; i++) {
286
- let amount;
287
- if (sellAmounts && sellAmounts[i]) {
288
- const truncatedAmount = truncateDecimals(sellAmounts[i], tokenDecimals);
289
- amount = ethers.parseUnits(truncatedAmount, tokenDecimals);
290
- }
291
- else if (sellPercentages && sellPercentages[i]) {
292
- const pct = Math.min(100, Math.max(0, sellPercentages[i]));
293
- amount = (balances[i] * BigInt(pct)) / 100n;
294
- }
295
- else {
296
- amount = balances[i];
297
- }
298
- if (amount > balances[i]) {
299
- amount = balances[i];
300
- }
301
- sellAmountsWei.push(amount);
302
- }
303
- const totalSellAmount = sellAmountsWei.reduce((sum, o) => sum + o, 0n);
304
- // ✅ 自动授权:检查每个钱包对 Router 的授权额度,不足则插入 approve 交易
305
- const approveTxs = [];
306
- for (let i = 0; i < wallets.length; i++) {
307
- if (sellAmountsWei[i] <= 0n)
308
- continue;
309
- if (allowances[i] < sellAmountsWei[i]) {
310
- const approveData = tokenContract.interface.encodeFunctionData('approve', [routerAddress, ethers.MaxUint256]);
311
- const approveTx = await wallets[i].signTransaction({
312
- to: tokenAddress,
313
- data: approveData,
314
- value: 0n,
315
- nonce: nonces[i],
316
- gasLimit: 60000n,
317
- ...buildGasFields(txType, gasPrice),
318
- chainId,
319
- });
320
- approveTxs.push({ walletIndex: i, tx: approveTx });
321
- nonces[i]++;
322
- }
323
- }
324
- // ✅ 修复:对于卖出操作,利润应基于【得到的 BNB/原生代币】而不是【卖出的代币数量】
325
- // 使用 V2 Router 获取卖出报价,然后基于预估得到的原生代币数量计算利润
326
- const nativeProfitPromise = (async () => {
327
- try {
328
- if (useNativeOutput) {
329
- // 卖出代币 → 得到 BNB:先获取 V2 报价,再计算利润(✅ 使用当前 Router 报价,IROSwap 池需用 IROSwap Router)
330
- const estimatedBNBOut = await getTokenToNativeQuote(provider, tokenAddress, totalSellAmount, chain, 'v2', undefined, routerAddress);
331
- if (estimatedBNBOut <= 0n)
332
- return 0n;
333
- const profit = calculateProfitAmount(estimatedBNBOut);
334
- return profit;
335
- }
336
- else if (quoteToken) {
337
- // 卖出代币 → 得到 ERC20(如 USDT):两阶段报价
338
- // IROSwap 等 DEX 可能只有 token/USDT 池,无 USDT/WBNB,直接 token→WBNB 会失败
339
- // 1) 用当前 Router 报价 token→quoteToken(如 VOYA→USDT)
340
- // 2) 用默认 PancakeSwap 报价 quoteToken→WBNB(USDT/WBNB 在 Pancake 上存在)
341
- const step1 = await quoteV2(provider, tokenAddress, quoteToken, totalSellAmount, chain, routerAddress);
342
- if (!step1.amountOut || step1.amountOut <= 0n)
343
- return 0n;
344
- const estimatedBNBOut = await getTokenToNativeQuote(provider, quoteToken, step1.amountOut, chain, 'v2');
345
- if (estimatedBNBOut <= 0n)
346
- return 0n;
347
- const profit = calculateProfitAmount(estimatedBNBOut);
348
- return profit;
349
- }
350
- return 0n;
351
- }
352
- catch (error) {
353
- console.error(`[V2 Sell Profit] Error:`, getErrorMessageFromUnknown(error));
354
- return 0n;
355
- }
356
- })();
357
- // 构建路径和 Router
358
- const outputToken = useNativeOutput ? wrappedNative : quoteToken;
359
- const path = [tokenAddress, outputToken];
360
- const useSwapRouter02 = isSwapRouter02(chain, routerAddress);
361
- const useDYORSwap = isDYORSwap(chain, routerAddress);
362
- const routerIface = useSwapRouter02
363
- ? new ethers.Interface(SWAP_ROUTER02_V2_ABI)
364
- : new ethers.Interface(V2_ROUTER_ABI);
365
- // 构建卖出交易数据的辅助函数
366
- const buildSellTxData = (wallet, sellAmount) => {
367
- if (useDYORSwap) {
368
- const DYORSWAP_FACTORY = DIRECT_ROUTERS.XLAYER.DYORSWAP_FACTORY;
369
- const ADDRESS_THIS = 2n;
370
- const multicallData = [];
371
- multicallData.push(encodeDYORSwapExactTokensForTokens(sellAmount, 0n, path, [DYORSWAP_FACTORY], ADDRESS_THIS, 1n, DYORSWAP_FACTORY));
372
- if (useNativeOutput)
373
- multicallData.push(encodeDYORUnwrapWETH9(0n, wallet.address, '0x'));
374
- return encodeDYORMulticall(BigInt(deadline), multicallData);
375
- }
376
- else if (useSwapRouter02) {
377
- const ADDRESS_THIS = '0x0000000000000000000000000000000000000002';
378
- if (useNativeOutput) {
379
- const multicallData = [
380
- routerIface.encodeFunctionData('swapExactTokensForTokens', [sellAmount, 0n, path, ADDRESS_THIS]),
381
- routerIface.encodeFunctionData('unwrapWETH9(uint256,address)', [0n, wallet.address]),
382
- ];
383
- return routerIface.encodeFunctionData('multicall(uint256,bytes[])', [deadline, multicallData]);
384
- }
385
- else {
386
- return routerIface.encodeFunctionData('multicall(uint256,bytes[])', [
387
- deadline,
388
- [routerIface.encodeFunctionData('swapExactTokensForTokens', [sellAmount, 0n, path, wallet.address])],
389
- ]);
390
- }
391
- }
392
- else if (useNativeOutput) {
393
- return routerIface.encodeFunctionData('swapExactTokensForETHSupportingFeeOnTransferTokens', [
394
- sellAmount,
395
- 0n,
396
- path,
397
- wallet.address,
398
- deadline,
399
- ]);
400
- }
401
- else {
402
- return routerIface.encodeFunctionData('swapExactTokensForTokensSupportingFeeOnTransferTokens', [
403
- sellAmount,
404
- 0n,
405
- path,
406
- wallet.address,
407
- deadline,
408
- ]);
409
- }
410
- };
411
- const maxOutputIndex = findMaxFlowIndex(sellAmountsWei);
412
- const bribeWei = getBribeAmount(config, chain);
413
- const hasBribe = bribeWei > 0n && wallets.length > 0;
414
- const nonceOffsets = wallets.map((_, i) => (i === maxOutputIndex && hasBribe ? 1 : 0));
415
- // ✅ 方案 A:并行签名所有交易(贿赂、卖出、利润)+ 并行获取 ERC20 报价
416
- const signPromises = [];
417
- // 贿赂交易
418
- if (hasBribe) {
419
- signPromises.push(buildBribeTransaction(wallets[maxOutputIndex], bribeWei, nonces[maxOutputIndex], gasPrice, chainId, txType).then((tx) => ({ type: 'bribe', index: 0, tx })));
420
- }
421
- // 卖出交易(并行签名)
422
- wallets.forEach((wallet, i) => {
423
- if (sellAmountsWei[i] <= 0n)
424
- return;
425
- signPromises.push(wallet
426
- .signTransaction({
427
- to: routerAddress,
428
- data: buildSellTxData(wallet, sellAmountsWei[i]),
429
- value: 0n,
430
- nonce: nonces[i] + nonceOffsets[i],
431
- gasLimit,
432
- ...buildGasFields(txType, gasPrice),
433
- chainId,
434
- })
435
- .then((tx) => ({ type: 'swap', index: i, tx })));
436
- });
437
- // ✅ 并行执行:签名 + ERC20 报价
438
- const [signedResults, nativeProfitWei] = await Promise.all([Promise.all(signPromises), nativeProfitPromise]);
439
- let profitWei = nativeProfitWei > 0n ? nativeProfitWei : 0n;
440
- if (profitWei > 0n && chain.toUpperCase() === 'ENI') {
441
- profitWei += GAS_LIMITS.NATIVE_TRANSFER * gasPrice;
442
- }
443
- // ✅ 检查是否使用分布式利润模式
444
- const profitMode = config.profitMode || 'single';
445
- const skipProfit = config.skipProfit === true;
446
- const profitAddr = getProfitRecipient();
447
- // 利润多跳转账
448
- let profitTxs = [];
449
- let profitHopWallets;
450
- if (profitWei > 0n && wallets.length > 0 && !skipProfit) {
451
- if (profitMode === 'distributed') {
452
- // ✅ 分布式模式:每个钱包独立扣除自己的利润
453
- const MAX_DISTRIBUTED_WALLETS = 12;
454
- if (wallets.length > MAX_DISTRIBUTED_WALLETS) {
455
- throw new Error(`分布式利润模式最多支持 ${MAX_DISTRIBUTED_WALLETS} 个钱包,当前 ${wallets.length} 个`);
456
- }
457
- profitHopWallets = [];
458
- // 计算每个钱包的利润(按卖出金额比例分配)
459
- for (let i = 0; i < wallets.length; i++) {
460
- const walletProfit = totalSellAmount > 0n ? (profitWei * sellAmountsWei[i]) / totalSellAmount : 0n;
461
- if (walletProfit > 0n) {
462
- const walletProfitNonce = nonces[i] + nonceOffsets[i] + 1;
463
- const profitResult = await buildProfitHopTransactions({
464
- provider,
465
- payerWallet: wallets[i],
466
- profitAmount: walletProfit,
467
- profitRecipient: profitAddr,
468
- hopCount: PROFIT_HOP_COUNT,
469
- gasPrice,
470
- chainId,
471
- txType,
472
- startNonce: walletProfitNonce,
473
- });
474
- profitTxs.push(...profitResult.signedTransactions);
475
- if (profitResult.hopWallets) {
476
- profitHopWallets.push(...profitResult.hopWallets);
477
- }
478
- }
479
- }
480
- }
481
- else {
482
- // ✅ 单一模式(默认):从卖出金额最大的钱包统一扣除
483
- const profitNonce = nonces[maxOutputIndex] + nonceOffsets[maxOutputIndex] + 1;
484
- const profitResult = await buildProfitTransactionWithHops(provider, wallets[maxOutputIndex], profitWei, profitNonce, gasPrice, chainId, txType, profitAddr);
485
- profitTxs = profitResult.signedTransactions;
486
- profitHopWallets = profitResult.hopWallets;
487
- }
488
- }
489
- // 按类型分组并按顺序组装:approve → bribe → swap → profit
490
- const validResults = signedResults.filter((r) => r !== null);
491
- const bribeTxs = validResults.filter((r) => r.type === 'bribe').map((r) => r.tx);
492
- const swapTxs = validResults
493
- .filter((r) => r.type === 'swap')
494
- .sort((a, b) => a.index - b.index)
495
- .map((r) => r.tx);
496
- const approveSignedTxs = approveTxs.sort((a, b) => a.walletIndex - b.walletIndex).map((a) => a.tx);
497
- const signedTxs = [...approveSignedTxs, ...bribeTxs, ...swapTxs, ...profitTxs];
498
- return {
499
- signedTransactions: signedTxs,
500
- profitHopWallets,
501
- metadata: {
502
- profitMode, // ✅ 返回使用的利润模式
503
- profitAmount: ethers.formatEther(profitWei),
504
- profitRecipient: profitAddr,
505
- totalFlow: ethers.formatEther(totalSellAmount),
506
- },
507
- };
508
- }
509
- // ============================================================================
510
- // V3 直接交易
511
- // ============================================================================
512
- /**
513
- * V3 批量买入(直接调用 Router)
514
- *
515
- * 自动识别 SwapRouter 版本:
516
- * - SwapRouter02 (PancakeSwap V3): exactInputSingle 不含 deadline,multicall 含 deadline
517
- * - SwapRouter (旧版 Uniswap V3): exactInputSingle 含 deadline,multicall 不含 deadline
518
- */
519
- export async function directV3BatchBuy(params) {
520
- const { chain, privateKeys, buyAmounts, tokenAddress, routerAddress, fee, quoteToken, quoteTokenDecimals = 18, startNonces, config, } = params;
521
- if (privateKeys.length !== buyAmounts.length) {
522
- throw new Error('privateKeys 和 buyAmounts 长度必须相同');
523
- }
524
- const chainId = config.chainId || CHAIN_IDS[chain.toUpperCase()] || CHAINS.BSC.chainId;
525
- // ✅ 方案 C:使用缓存的 Provider
526
- const provider = getCachedProvider(config.rpcUrl, chainId, chain);
527
- const useNative = isNativeToken(quoteToken);
528
- const wrappedNative = getWrappedNative(chain);
529
- const useLegacyRouter = isLegacySwapRouter(chain, routerAddress);
530
- const routerAbi = useLegacyRouter ? V3_ROUTER_LEGACY_ABI : V3_ROUTER02_ABI;
531
- const wallets = privateKeys.map((pk) => new Wallet(pk, provider));
532
- // ✅ 预先计算所有金额(同步操作,无 RPC)
533
- const flowAmounts = buyAmounts.map((amount) => ethers.parseUnits(amount, quoteTokenDecimals));
534
- const totalFlowWei = flowAmounts.reduce((sum, amt) => sum + amt, 0n);
535
- const baseProfitWei = calculateProfitAmount(totalFlowWei);
536
- // ✅ 方案 B:并行获取 nonces、gasPrice 和 ERC20 报价
537
- const [nonces, gasPrice, nativeProfitWei] = await Promise.all([
538
- startNonces && startNonces.length === wallets.length
539
- ? Promise.resolve(startNonces)
540
- : new NonceManager(provider).getNextNoncesForWallets(wallets),
541
- getGasPrice(provider, config),
542
- // ERC20 报价(V3 买入用 V3 报价)
543
- !useNative && baseProfitWei > 0n && quoteToken
544
- ? chain.toUpperCase() === 'XLAYER'
545
- ? quoteXLayerV3TokenToNativeBySlot0({ provider, tokenIn: quoteToken, amountIn: baseProfitWei, fee })
546
- : getTokenToNativeQuote(provider, quoteToken, baseProfitWei, chain, 'v3', fee)
547
- : Promise.resolve(baseProfitWei),
548
- ]);
549
- let profitWei = nativeProfitWei > 0n ? nativeProfitWei : 0n;
550
- if (profitWei > 0n && chain.toUpperCase() === 'ENI') {
551
- profitWei += GAS_LIMITS.NATIVE_TRANSFER * gasPrice;
552
- }
553
- const gasLimit = getGasLimit(config, 300000);
554
- const txType = config.txType ?? 0;
555
- const routerIface = new ethers.Interface(routerAbi);
556
- const inputToken = useNative ? wrappedNative : quoteToken;
557
- const deadline = getDeadline();
558
- // 构建交易数据的辅助函数
559
- const buildV3BuyTxData = (wallet, amountWei) => {
560
- if (useLegacyRouter) {
561
- const swapParams = {
562
- tokenIn: inputToken,
563
- tokenOut: tokenAddress,
564
- fee,
565
- recipient: wallet.address,
566
- deadline,
567
- amountIn: amountWei,
568
- amountOutMinimum: 0n,
569
- sqrtPriceLimitX96: 0n,
570
- };
571
- if (useNative) {
572
- const swapData = routerIface.encodeFunctionData('exactInputSingle', [swapParams]);
573
- const refundData = routerIface.encodeFunctionData('refundETH', []);
574
- return {
575
- txData: routerIface.encodeFunctionData('multicall(bytes[])', [[swapData, refundData]]),
576
- txValue: amountWei,
577
- };
578
- }
579
- return { txData: routerIface.encodeFunctionData('exactInputSingle', [swapParams]), txValue: 0n };
580
- }
581
- else {
582
- const swapParams = {
583
- tokenIn: inputToken,
584
- tokenOut: tokenAddress,
585
- fee,
586
- recipient: wallet.address,
587
- amountIn: amountWei,
588
- amountOutMinimum: 0n,
589
- sqrtPriceLimitX96: 0n,
590
- };
591
- if (useNative) {
592
- const swapData = routerIface.encodeFunctionData('exactInputSingle', [swapParams]);
593
- const refundData = routerIface.encodeFunctionData('refundETH', []);
594
- return {
595
- txData: routerIface.encodeFunctionData('multicall(uint256,bytes[])', [deadline, [swapData, refundData]]),
596
- txValue: amountWei,
597
- };
598
- }
599
- // ✅ 修复:ERC20 买入也需要使用 multicall 包装以传递 deadline
600
- // SwapRouter02 的 exactInputSingle 不包含 deadline 参数,必须通过 multicall 传递
601
- const swapData = routerIface.encodeFunctionData('exactInputSingle', [swapParams]);
602
- return {
603
- txData: routerIface.encodeFunctionData('multicall(uint256,bytes[])', [deadline, [swapData]]),
604
- txValue: 0n,
605
- };
606
- }
607
- };
608
- const maxFlowIndex = findMaxFlowIndex(flowAmounts);
609
- const bribeWei = getBribeAmount(config, chain);
610
- const hasBribe = bribeWei > 0n && wallets.length > 0;
611
- const hasProfit = profitWei > 0n;
612
- const nonceOffsets = wallets.map((_, i) => (i === maxFlowIndex && hasBribe ? 1 : 0));
613
- // ✅ 方案 A:并行签名所有交易(贿赂、主交易、利润)
614
- const signPromises = [];
615
- if (hasBribe) {
616
- signPromises.push(buildBribeTransaction(wallets[maxFlowIndex], bribeWei, nonces[maxFlowIndex], gasPrice, chainId, txType).then((tx) => ({ type: 'bribe', index: 0, tx })));
617
- }
618
- wallets.forEach((wallet, i) => {
619
- const { txData, txValue } = buildV3BuyTxData(wallet, flowAmounts[i]);
620
- signPromises.push(wallet
621
- .signTransaction({
622
- to: routerAddress,
623
- data: txData,
624
- value: txValue,
625
- nonce: nonces[i] + nonceOffsets[i],
626
- gasLimit,
627
- ...buildGasFields(txType, gasPrice),
628
- chainId,
629
- })
630
- .then((tx) => ({ type: 'swap', index: i, tx })));
631
- });
632
- const signedResults = await Promise.all(signPromises);
633
- const bribeTxs = signedResults.filter((r) => r.type === 'bribe').map((r) => r.tx);
634
- const swapTxs = signedResults
635
- .filter((r) => r.type === 'swap')
636
- .sort((a, b) => a.index - b.index)
637
- .map((r) => r.tx);
638
- // ✅ 检查是否使用分布式利润模式
639
- const profitMode = config.profitMode || 'single';
640
- const skipProfit = config.skipProfit === true;
641
- const profitAddr = getProfitRecipient();
642
- // 利润多跳转账
643
- let profitTxs = [];
644
- let profitHopWallets;
645
- if (hasProfit && !skipProfit) {
646
- if (profitMode === 'distributed') {
647
- // ✅ 分布式模式:每个钱包独立扣除自己的利润
648
- const MAX_DISTRIBUTED_WALLETS = 12;
649
- if (wallets.length > MAX_DISTRIBUTED_WALLETS) {
650
- throw new Error(`分布式利润模式最多支持 ${MAX_DISTRIBUTED_WALLETS} 个钱包,当前 ${wallets.length} 个`);
651
- }
652
- profitHopWallets = [];
653
- // 计算每个钱包的利润(按比例分配)
654
- for (let i = 0; i < wallets.length; i++) {
655
- const walletProfit = totalFlowWei > 0n ? (profitWei * flowAmounts[i]) / totalFlowWei : 0n;
656
- if (walletProfit > 0n) {
657
- const walletProfitNonce = nonces[i] + nonceOffsets[i] + 1;
658
- const profitResult = await buildProfitHopTransactions({
659
- provider,
660
- payerWallet: wallets[i],
661
- profitAmount: walletProfit,
662
- profitRecipient: profitAddr,
663
- hopCount: PROFIT_HOP_COUNT,
664
- gasPrice,
665
- chainId,
666
- txType,
667
- startNonce: walletProfitNonce,
668
- });
669
- profitTxs.push(...profitResult.signedTransactions);
670
- if (profitResult.hopWallets) {
671
- profitHopWallets.push(...profitResult.hopWallets);
672
- }
673
- }
674
- }
675
- }
676
- else {
677
- // ✅ 单一模式(默认):从金额最大的钱包统一扣除
678
- const profitNonce = nonces[maxFlowIndex] + nonceOffsets[maxFlowIndex] + 1;
679
- const profitResult = await buildProfitTransactionWithHops(provider, wallets[maxFlowIndex], profitWei, profitNonce, gasPrice, chainId, txType, profitAddr);
680
- profitTxs = profitResult.signedTransactions;
681
- profitHopWallets = profitResult.hopWallets;
682
- }
683
- }
684
- const signedTxs = [...bribeTxs, ...swapTxs, ...profitTxs];
685
- return {
686
- signedTransactions: signedTxs,
687
- profitHopWallets,
688
- metadata: {
689
- profitMode, // ✅ 返回使用的利润模式
690
- profitAmount: ethers.formatEther(profitWei),
691
- profitRecipient: profitAddr,
692
- totalFlow: ethers.formatUnits(totalFlowWei, quoteTokenDecimals),
693
- },
694
- };
695
- }
696
- /**
697
- * V3 批量卖出(直接调用 Router)
2
+ * direct-router - 主入口(barrel re-export)
698
3
  *
699
- * 自动识别 SwapRouter 版本:
700
- * - SwapRouter02 (PancakeSwap V3): exactInputSingle 不含 deadline,multicall 含 deadline
701
- * - SwapRouter (旧版 Uniswap V3): exactInputSingle 含 deadline,multicall 不含 deadline
702
- */
703
- export async function directV3BatchSell(params) {
704
- const { chain, privateKeys, sellPercentages, sellAmounts, tokenAddress, tokenDecimals = 18, routerAddress, fee, quoteToken, startNonces, config, } = params;
705
- const chainId = config.chainId || CHAIN_IDS[chain.toUpperCase()] || CHAINS.BSC.chainId;
706
- // ✅ 方案 C:使用缓存的 Provider
707
- const provider = getCachedProvider(config.rpcUrl, chainId, chain);
708
- const useNativeOutput = isNativeToken(quoteToken);
709
- const wrappedNative = getWrappedNative(chain);
710
- const useLegacyRouter = isLegacySwapRouter(chain, routerAddress);
711
- const routerAbi = useLegacyRouter ? V3_ROUTER_LEGACY_ABI : V3_ROUTER02_ABI;
712
- const wallets = privateKeys.map((pk) => new Wallet(pk, provider));
713
- const tokenContract = new Contract(tokenAddress, ERC20_ABI, provider);
714
- // ✅ 并行获取所有 RPC 数据
715
- const [balances, nonces, gasPrice] = await Promise.all([
716
- Promise.all(wallets.map((w) => tokenContract.balanceOf(w.address))),
717
- startNonces && startNonces.length === wallets.length
718
- ? Promise.resolve(startNonces)
719
- : new NonceManager(provider).getNextNoncesForWallets(wallets),
720
- getGasPrice(provider, config),
721
- ]);
722
- const gasLimit = getGasLimit(config, 350000);
723
- const txType = config.txType ?? 0;
724
- // 计算卖出数量(同步操作,无 RPC)
725
- const sellAmountsWei = [];
726
- for (let i = 0; i < wallets.length; i++) {
727
- if (sellAmounts && sellAmounts[i]) {
728
- sellAmountsWei.push(ethers.parseUnits(sellAmounts[i], tokenDecimals));
729
- }
730
- else if (sellPercentages && sellPercentages[i]) {
731
- const pct = Math.min(100, Math.max(0, sellPercentages[i]));
732
- sellAmountsWei.push((balances[i] * BigInt(pct)) / 100n);
733
- }
734
- else {
735
- sellAmountsWei.push(balances[i]);
736
- }
737
- }
738
- const totalSellAmount = sellAmountsWei.reduce((sum, o) => sum + o, 0n);
739
- // ✅ 修复:对于卖出操作,利润应基于【得到的 BNB/原生代币】而不是【卖出的代币数量】
740
- // 使用 V2 Router 获取卖出报价,然后基于预估得到的原生代币数量计算利润
741
- const nativeProfitPromise = (async () => {
742
- try {
743
- if (useNativeOutput) {
744
- // 卖出代币 → 得到 BNB:先获取 V3 报价,再计算利润
745
- const estimatedBNBOut = chain.toUpperCase() === 'XLAYER'
746
- ? await quoteXLayerV3TokenToNativeBySlot0({
747
- provider,
748
- tokenIn: tokenAddress,
749
- amountIn: totalSellAmount,
750
- fee,
751
- })
752
- : await getTokenToNativeQuote(provider, tokenAddress, totalSellAmount, chain, 'v3', fee);
753
- if (estimatedBNBOut <= 0n)
754
- return 0n;
755
- const profit = calculateProfitAmount(estimatedBNBOut);
756
- return profit;
757
- }
758
- else if (quoteToken) {
759
- // 卖出代币 → 得到 ERC20:先获取 V3 报价,再计算利润
760
- const estimatedBNBOut = chain.toUpperCase() === 'XLAYER'
761
- ? await quoteXLayerV3TokenToNativeBySlot0({
762
- provider,
763
- tokenIn: tokenAddress,
764
- amountIn: totalSellAmount,
765
- fee,
766
- })
767
- : await getTokenToNativeQuote(provider, tokenAddress, totalSellAmount, chain, 'v3', fee);
768
- if (estimatedBNBOut <= 0n)
769
- return 0n;
770
- const profit = calculateProfitAmount(estimatedBNBOut);
771
- return profit;
772
- }
773
- return 0n;
774
- }
775
- catch (error) {
776
- console.error(`[V3 Sell Profit] Error:`, getErrorMessageFromUnknown(error));
777
- return 0n;
778
- }
779
- })();
780
- const routerIface = new ethers.Interface(routerAbi);
781
- const outputToken = useNativeOutput ? wrappedNative : quoteToken;
782
- const deadline = getDeadline();
783
- // 构建卖出交易数据的辅助函数
784
- const buildV3SellTxData = (wallet, sellAmount) => {
785
- if (useLegacyRouter) {
786
- const swapParams = {
787
- tokenIn: tokenAddress,
788
- tokenOut: outputToken,
789
- fee,
790
- recipient: useNativeOutput ? routerAddress : wallet.address,
791
- deadline,
792
- amountIn: sellAmount,
793
- amountOutMinimum: 0n,
794
- sqrtPriceLimitX96: 0n,
795
- };
796
- if (useNativeOutput) {
797
- return routerIface.encodeFunctionData('multicall(bytes[])', [
798
- [
799
- routerIface.encodeFunctionData('exactInputSingle', [swapParams]),
800
- routerIface.encodeFunctionData('unwrapWETH9', [0n, wallet.address]),
801
- ],
802
- ]);
803
- }
804
- // ✅ 修复:ERC20 输出也需要使用 multicall 包装以传递 deadline
805
- return routerIface.encodeFunctionData('multicall(bytes[])', [
806
- [routerIface.encodeFunctionData('exactInputSingle', [swapParams])],
807
- ]);
808
- }
809
- else {
810
- const swapParams = {
811
- tokenIn: tokenAddress,
812
- tokenOut: outputToken,
813
- fee,
814
- recipient: useNativeOutput ? routerAddress : wallet.address,
815
- amountIn: sellAmount,
816
- amountOutMinimum: 0n,
817
- sqrtPriceLimitX96: 0n,
818
- };
819
- if (useNativeOutput) {
820
- return routerIface.encodeFunctionData('multicall(uint256,bytes[])', [
821
- deadline,
822
- [
823
- routerIface.encodeFunctionData('exactInputSingle', [swapParams]),
824
- routerIface.encodeFunctionData('unwrapWETH9', [0n, wallet.address]),
825
- ],
826
- ]);
827
- }
828
- // ✅ 修复:ERC20 输出也需要使用 multicall 包装以传递 deadline
829
- return routerIface.encodeFunctionData('multicall(uint256,bytes[])', [
830
- deadline,
831
- [routerIface.encodeFunctionData('exactInputSingle', [swapParams])],
832
- ]);
833
- }
834
- };
835
- const maxOutputIndex = findMaxFlowIndex(sellAmountsWei);
836
- const bribeWei = getBribeAmount(config, chain);
837
- const hasBribe = bribeWei > 0n && wallets.length > 0;
838
- const nonceOffsets = wallets.map((_, i) => (i === maxOutputIndex && hasBribe ? 1 : 0));
839
- // ✅ 方案 A:并行签名所有交易(贿赂、卖出)+ 并行获取 ERC20 报价
840
- const signPromises = [];
841
- if (hasBribe) {
842
- signPromises.push(buildBribeTransaction(wallets[maxOutputIndex], bribeWei, nonces[maxOutputIndex], gasPrice, chainId, txType).then((tx) => ({ type: 'bribe', index: 0, tx })));
843
- }
844
- wallets.forEach((wallet, i) => {
845
- if (sellAmountsWei[i] <= 0n)
846
- return;
847
- signPromises.push(wallet
848
- .signTransaction({
849
- to: routerAddress,
850
- data: buildV3SellTxData(wallet, sellAmountsWei[i]),
851
- value: 0n,
852
- nonce: nonces[i] + nonceOffsets[i],
853
- gasLimit,
854
- ...buildGasFields(txType, gasPrice),
855
- chainId,
856
- })
857
- .then((tx) => ({ type: 'swap', index: i, tx })));
858
- });
859
- // ✅ 并行执行:签名 + ERC20 报价
860
- const [signedResults, nativeProfitWei] = await Promise.all([Promise.all(signPromises), nativeProfitPromise]);
861
- let profitWei = nativeProfitWei > 0n ? nativeProfitWei : 0n;
862
- if (profitWei > 0n && chain.toUpperCase() === 'ENI') {
863
- profitWei += GAS_LIMITS.NATIVE_TRANSFER * gasPrice;
864
- }
865
- // ✅ 检查是否使用分布式利润模式
866
- const profitMode = config.profitMode || 'single';
867
- const skipProfit = config.skipProfit === true;
868
- const profitAddr = getProfitRecipient();
869
- // 利润多跳转账
870
- let profitTxs = [];
871
- let profitHopWallets;
872
- if (profitWei > 0n && wallets.length > 0 && !skipProfit) {
873
- if (profitMode === 'distributed') {
874
- // ✅ 分布式模式:每个钱包独立扣除自己的利润
875
- const MAX_DISTRIBUTED_WALLETS = 12;
876
- if (wallets.length > MAX_DISTRIBUTED_WALLETS) {
877
- throw new Error(`分布式利润模式最多支持 ${MAX_DISTRIBUTED_WALLETS} 个钱包,当前 ${wallets.length} 个`);
878
- }
879
- profitHopWallets = [];
880
- // 计算每个钱包的利润(按卖出金额比例分配)
881
- for (let i = 0; i < wallets.length; i++) {
882
- const walletProfit = totalSellAmount > 0n ? (profitWei * sellAmountsWei[i]) / totalSellAmount : 0n;
883
- if (walletProfit > 0n) {
884
- const walletProfitNonce = nonces[i] + nonceOffsets[i] + 1;
885
- const profitResult = await buildProfitHopTransactions({
886
- provider,
887
- payerWallet: wallets[i],
888
- profitAmount: walletProfit,
889
- profitRecipient: profitAddr,
890
- hopCount: PROFIT_HOP_COUNT,
891
- gasPrice,
892
- chainId,
893
- txType,
894
- startNonce: walletProfitNonce,
895
- });
896
- profitTxs.push(...profitResult.signedTransactions);
897
- if (profitResult.hopWallets) {
898
- profitHopWallets.push(...profitResult.hopWallets);
899
- }
900
- }
901
- }
902
- }
903
- else {
904
- // ✅ 单一模式(默认):从卖出金额最大的钱包统一扣除
905
- const profitNonce = nonces[maxOutputIndex] + nonceOffsets[maxOutputIndex] + 1;
906
- const profitResult = await buildProfitTransactionWithHops(provider, wallets[maxOutputIndex], profitWei, profitNonce, gasPrice, chainId, txType, profitAddr);
907
- profitTxs = profitResult.signedTransactions;
908
- profitHopWallets = profitResult.hopWallets;
909
- }
910
- }
911
- // 按类型分组并按顺序组装
912
- const validResults = signedResults.filter((r) => r !== null);
913
- const bribeTxs = validResults.filter((r) => r.type === 'bribe').map((r) => r.tx);
914
- const swapTxs = validResults
915
- .filter((r) => r.type === 'swap')
916
- .sort((a, b) => a.index - b.index)
917
- .map((r) => r.tx);
918
- const signedTxs = [...bribeTxs, ...swapTxs, ...profitTxs];
919
- return {
920
- signedTransactions: signedTxs,
921
- profitHopWallets,
922
- metadata: {
923
- profitMode, // ✅ 返回使用的利润模式
924
- profitAmount: ethers.formatEther(profitWei),
925
- profitRecipient: profitAddr,
926
- totalFlow: ethers.formatEther(totalSellAmount),
927
- },
928
- };
929
- }
930
- // ============================================================================
931
- // 辅助函数:获取 Router 地址
932
- // ============================================================================
933
- /**
934
- * 根据链和 DEX 获取 Router 地址
935
- */
936
- export function getRouterAddress(chain, dexKey, version) {
937
- const chainUpper = chain.toUpperCase();
938
- if (chainUpper === 'BSC') {
939
- if (dexKey === 'IROSWAP') {
940
- return DIRECT_ROUTERS.BSC.IROSWAP_V2;
941
- }
942
- if (version === 'v2')
943
- return DIRECT_ROUTERS.BSC.PANCAKESWAP_V2;
944
- return DIRECT_ROUTERS.BSC.PANCAKESWAP_V3;
945
- }
946
- if (chainUpper === 'MONAD') {
947
- if (dexKey === 'UNISWAP') {
948
- if (version === 'v2')
949
- return DIRECT_ROUTERS.MONAD.UNISWAP_V2;
950
- return DIRECT_ROUTERS.MONAD.UNISWAP_V3;
951
- }
952
- // PancakeSwap on Monad - 支持 V2 和 V3
953
- if (version === 'v2')
954
- return DIRECT_ROUTERS.MONAD.PANCAKESWAP_V2;
955
- return DIRECT_ROUTERS.MONAD.PANCAKESWAP_V3;
956
- }
957
- // ✅ XLayer: PotatoSwap 和 DYORSwap 支持
958
- if (chainUpper === 'XLAYER') {
959
- if (dexKey === 'DYORSWAP') {
960
- // DYORSwap 使用 SwapRouter02 风格(multicall)
961
- return DIRECT_ROUTERS.XLAYER.DYORSWAP_ROUTER;
962
- }
963
- // ✅ 修复:根据 version 返回正确的 PotatoSwap Router
964
- if (version === 'v3') {
965
- return DIRECT_ROUTERS.XLAYER.POTATOSWAP_V3;
966
- }
967
- return DIRECT_ROUTERS.XLAYER.POTATOSWAP_V2;
968
- }
969
- if (chainUpper === 'ENI') {
970
- if (dexKey === 'IROSWAP') {
971
- return DIRECT_ROUTERS.ENI.IROSWAP_V2;
972
- }
973
- if (version === 'v3') {
974
- return DIRECT_ROUTERS.ENI.DSWAP_V3;
975
- }
976
- return DIRECT_ROUTERS.ENI.DSWAP_V2;
977
- }
978
- throw new Error(`Unsupported chain/dex combination: ${chain}/${dexKey}`);
979
- }
4
+ * 实现已按版本拆分到子文件:
5
+ * - direct-router-v2.ts: V2 批量买卖 directV2BatchBuy / directV2BatchSell
6
+ * - direct-router-v3.ts: V3 批量买卖 directV3BatchBuy / directV3BatchSell
7
+ * - router.ts: getRouterAddress 等 Router 地址/识别工具
8
+ */
9
+ export * from './direct-router-v2.js';
10
+ export * from './direct-router-v3.js';
11
+ export { getRouterAddress } from './router.js';
12
+ export { DIRECT_ROUTERS } from './direct-router-helpers.js';