four-flap-meme-sdk 1.9.49 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (567) hide show
  1. package/README.en.md +41 -6
  2. package/README.md +31 -0
  3. package/README.zh-CN.md +41 -6
  4. package/dist/__tests__/subpath-exports.test.js +34 -0
  5. package/dist/abis/common.js +74 -68
  6. package/dist/abis/flap/vault.js +9 -7
  7. package/dist/abis/index.d.ts +3 -4
  8. package/dist/abis/index.js +3 -4
  9. package/dist/bundle-core/__tests__/config-helpers.test.js +28 -0
  10. package/dist/bundle-core/__tests__/facade-parity.test.js +33 -0
  11. package/dist/bundle-core/__tests__/sign-context-helpers.test.js +60 -0
  12. package/dist/bundle-core/__tests__/sign-fixture.test.js +220 -0
  13. package/dist/bundle-core/__tests__/sign-fixtures.d.ts +10 -0
  14. package/dist/bundle-core/__tests__/sign-fixtures.js +16 -0
  15. package/dist/bundle-core/config-helpers.d.ts +36 -0
  16. package/dist/bundle-core/config-helpers.js +57 -0
  17. package/dist/bundle-core/errors.d.ts +50 -0
  18. package/dist/bundle-core/errors.js +34 -0
  19. package/dist/bundle-core/four-meme/approve-tokenmanager.d.ts +7 -0
  20. package/dist/bundle-core/four-meme/approve-tokenmanager.js +99 -0
  21. package/dist/bundle-core/four-meme/core-helpers.d.ts +8 -0
  22. package/dist/bundle-core/four-meme/core-helpers.js +40 -0
  23. package/dist/bundle-core/four-meme/core.d.ts +4 -0
  24. package/dist/bundle-core/four-meme/core.js +515 -0
  25. package/dist/bundle-core/four-meme/pancake-proxy.d.ts +28 -0
  26. package/dist/{shared 2/flap/portal-bundle-merkle/pancake-proxy.js → bundle-core/four-meme/pancake-proxy.js} +277 -299
  27. package/dist/bundle-core/four-meme/private.d.ts +27 -0
  28. package/dist/bundle-core/four-meme/private.js +465 -0
  29. package/dist/bundle-core/four-meme/sign-context-helpers.d.ts +2 -0
  30. package/dist/bundle-core/four-meme/sign-context-helpers.js +2 -0
  31. package/dist/bundle-core/four-meme/swap-buy-first.d.ts +8 -0
  32. package/dist/bundle-core/four-meme/swap-buy-first.js +493 -0
  33. package/dist/bundle-core/four-meme/swap-hop-helpers.d.ts +6 -0
  34. package/dist/bundle-core/four-meme/swap-hop-helpers.js +63 -0
  35. package/dist/bundle-core/four-meme/swap-internal.d.ts +3 -0
  36. package/dist/bundle-core/four-meme/swap-internal.js +18 -0
  37. package/dist/bundle-core/four-meme/swap-sign-helpers.d.ts +27 -0
  38. package/dist/bundle-core/four-meme/swap-sign-helpers.js +105 -0
  39. package/dist/bundle-core/four-meme/swap.d.ts +17 -0
  40. package/dist/{chains/bsc/four/swap/index.js → bundle-core/four-meme/swap.js} +84 -408
  41. package/dist/bundle-core/four-meme/types/buy-first.d.ts +50 -0
  42. package/dist/bundle-core/four-meme/types/core-flow.d.ts +63 -0
  43. package/dist/bundle-core/four-meme/types/index.d.ts +600 -0
  44. package/dist/bundle-core/four-meme/types/swap-internal.d.ts +19 -0
  45. package/dist/bundle-core/four-meme/types.d.ts +1 -0
  46. package/dist/bundle-core/four-meme/utils-disperse.d.ts +7 -0
  47. package/dist/bundle-core/four-meme/utils-disperse.js +396 -0
  48. package/dist/bundle-core/four-meme/utils-pairwise.d.ts +8 -0
  49. package/dist/bundle-core/four-meme/utils-pairwise.js +328 -0
  50. package/dist/bundle-core/four-meme/utils-sweep.d.ts +8 -0
  51. package/dist/bundle-core/four-meme/utils-sweep.js +744 -0
  52. package/dist/bundle-core/index.d.ts +8 -0
  53. package/dist/bundle-core/index.js +8 -0
  54. package/dist/bundle-core/internal.d.ts +21 -0
  55. package/dist/bundle-core/internal.js +182 -0
  56. package/dist/bundle-core/sign-context-helpers.d.ts +25 -0
  57. package/dist/bundle-core/sign-context-helpers.js +67 -0
  58. package/dist/bundle-core/submit.d.ts +293 -0
  59. package/dist/bundle-core/submit.js +727 -0
  60. package/dist/bundle-core/types/index.d.ts +8 -0
  61. package/dist/bundle-core/types.d.ts +1 -0
  62. package/dist/chains/bsc/four/approve-tokenmanager.d.ts +1 -26
  63. package/dist/chains/bsc/four/approve-tokenmanager.js +1 -116
  64. package/dist/chains/bsc/four/config.d.ts +5 -70
  65. package/dist/chains/bsc/four/config.js +2 -115
  66. package/dist/chains/bsc/four/core.d.ts +1 -4
  67. package/dist/chains/bsc/four/core.js +1 -589
  68. package/dist/chains/bsc/four/index.d.ts +6 -6
  69. package/dist/chains/bsc/four/index.js +6 -6
  70. package/dist/chains/bsc/four/internal.d.ts +2 -50
  71. package/dist/chains/bsc/four/internal.js +2 -237
  72. package/dist/chains/bsc/four/pancake-proxy.d.ts +1 -28
  73. package/dist/chains/bsc/four/pancake-proxy.js +1 -688
  74. package/dist/chains/bsc/four/private.d.ts +1 -27
  75. package/dist/chains/bsc/four/private.js +1 -477
  76. package/dist/chains/bsc/four/submit.d.ts +2 -315
  77. package/dist/chains/bsc/four/submit.js +2 -746
  78. package/dist/chains/bsc/four/swap-buy-first.d.ts +2 -55
  79. package/dist/chains/bsc/four/swap-buy-first.js +2 -506
  80. package/dist/chains/bsc/four/swap-internal.d.ts +1 -3
  81. package/dist/chains/bsc/four/swap-internal.js +1 -18
  82. package/dist/chains/bsc/four/swap.d.ts +2 -144
  83. package/dist/chains/bsc/four/swap.js +2 -760
  84. package/dist/chains/bsc/four/types.d.ts +1 -476
  85. package/dist/chains/bsc/four/utils-disperse.d.ts +1 -0
  86. package/dist/chains/bsc/four/utils-disperse.js +1 -0
  87. package/dist/chains/bsc/four/utils-pairwise.d.ts +1 -0
  88. package/dist/chains/bsc/four/utils-pairwise.js +1 -0
  89. package/dist/chains/bsc/four/utils-sweep.d.ts +1 -0
  90. package/dist/chains/bsc/four/utils-sweep.js +1 -0
  91. package/dist/chains/bsc/four/utils.d.ts +5 -18
  92. package/dist/chains/bsc/four/utils.js +5 -1534
  93. package/dist/chains/bsc/pancake/bundle-buy-first-helpers.d.ts +159 -0
  94. package/dist/chains/bsc/pancake/bundle-buy-first-helpers.js +117 -0
  95. package/dist/chains/bsc/pancake/bundle-buy-first.d.ts +1 -91
  96. package/dist/chains/bsc/pancake/bundle-buy-first.js +97 -207
  97. package/dist/chains/bsc/pancake/bundle-swap-helpers.d.ts +241 -0
  98. package/dist/chains/bsc/pancake/{bundle-swap/helpers.js → bundle-swap-helpers.js} +63 -70
  99. package/dist/chains/bsc/pancake/bundle-swap.d.ts +1 -79
  100. package/dist/chains/bsc/pancake/bundle-swap.js +111 -686
  101. package/dist/chains/bsc/pancake/index.d.ts +4 -2
  102. package/dist/chains/bsc/pancake/index.js +1 -3
  103. package/dist/chains/bsc/platforms/iro/factory.js +3 -1
  104. package/dist/chains/bsc/platforms/iro/index.d.ts +5 -5
  105. package/dist/chains/bsc/platforms/iro/index.js +3 -3
  106. package/dist/chains/bsc/platforms/iro/pool.js +31 -10
  107. package/dist/chains/bsc/platforms/iro/token.js +4 -1
  108. package/dist/chains/eni/batch-router/bundle-approve.js +4 -3
  109. package/dist/chains/eni/batch-router/transfer.js +54 -23
  110. package/dist/chains/eni/batch-router/utils.js +32 -6
  111. package/dist/chains/eni/bundler/sign.js +4 -4
  112. package/dist/chains/eni/bundler/submit.js +1 -4
  113. package/dist/chains/eni/constants.js +1 -1
  114. package/dist/chains/eni/index.d.ts +1 -1
  115. package/dist/chains/eni/platforms/daoaas/create.js +2 -2
  116. package/dist/chains/eni/platforms/daoaas/index.d.ts +3 -3
  117. package/dist/chains/eni/platforms/daoaas/index.js +3 -3
  118. package/dist/chains/eni/platforms/daoaas/meta.js +8 -4
  119. package/dist/chains/eni/platforms/daoaas/portal-direct.js +28 -43
  120. package/dist/chains/eni/platforms/daoaas/portal.js +10 -6
  121. package/dist/chains/eni/platforms/dswap/liquidity.js +58 -26
  122. package/dist/chains/eni/platforms/fair-launch/index.d.ts +2 -2
  123. package/dist/chains/eni/platforms/fair-launch/index.js +1 -1
  124. package/dist/chains/eni/platforms/fair-launch/launcher.js +87 -47
  125. package/dist/chains/eni/platforms/fair-launch/pool.js +4 -1
  126. package/dist/chains/eni/platforms/fair-launch/presets.js +2 -2
  127. package/dist/chains/eni/platforms/iro/factory.js +3 -1
  128. package/dist/chains/eni/platforms/iro/index.d.ts +6 -6
  129. package/dist/chains/eni/platforms/iro/index.js +4 -4
  130. package/dist/chains/eni/platforms/iro/pool.js +90 -26
  131. package/dist/chains/eni/platforms/iro/token.js +107 -31
  132. package/dist/chains/eni/platforms/iro/whitelist.js +6 -18
  133. package/dist/chains/eni/submit.js +5 -13
  134. package/dist/chains/index.d.ts +13 -0
  135. package/dist/chains/index.js +13 -0
  136. package/dist/chains/xlayer/eip7702/bundle-approve.d.ts +2 -26
  137. package/dist/chains/xlayer/eip7702/bundle-approve.js +11 -20
  138. package/dist/chains/xlayer/eip7702/bundle-buy.d.ts +2 -6
  139. package/dist/chains/xlayer/eip7702/bundle-buy.js +13 -51
  140. package/dist/chains/xlayer/eip7702/bundle-create.js +93 -56
  141. package/dist/chains/xlayer/eip7702/bundle-sell.d.ts +2 -6
  142. package/dist/chains/xlayer/eip7702/bundle-sell.js +26 -74
  143. package/dist/chains/xlayer/eip7702/bundle-swap.d.ts +3 -65
  144. package/dist/chains/xlayer/eip7702/bundle-swap.js +51 -68
  145. package/dist/chains/xlayer/eip7702/constants.d.ts +1 -16
  146. package/dist/chains/xlayer/eip7702/constants.js +3 -21
  147. package/dist/chains/xlayer/eip7702/index.d.ts +29 -46
  148. package/dist/chains/xlayer/eip7702/index.js +27 -81
  149. package/dist/chains/xlayer/eip7702/{multi-hop-transfer/types.d.ts → multi-hop-transfer-helpers.d.ts} +17 -23
  150. package/dist/chains/xlayer/eip7702/multi-hop-transfer.d.ts +2 -203
  151. package/dist/chains/xlayer/eip7702/multi-hop-transfer.js +58 -291
  152. package/dist/chains/xlayer/eip7702/transfer-context-helpers.d.ts +26 -0
  153. package/dist/chains/xlayer/eip7702/transfer-context-helpers.js +57 -0
  154. package/dist/chains/xlayer/eip7702/types.d.ts +88 -0
  155. package/dist/chains/xlayer/eip7702/utils.d.ts +0 -3
  156. package/dist/chains/xlayer/eip7702/utils.js +23 -28
  157. package/dist/chains/xlayer/eip7702/{volume/types.d.ts → volume-helpers.d.ts} +41 -17
  158. package/dist/chains/xlayer/eip7702/volume-helpers.js +48 -0
  159. package/dist/chains/xlayer/eip7702/volume.d.ts +6 -184
  160. package/dist/chains/xlayer/eip7702/volume.js +83 -158
  161. package/dist/chains/xlayer/eoa/constants.js +1 -1
  162. package/dist/chains/xlayer/eoa/dex-helpers.js +5 -5
  163. package/dist/chains/xlayer/eoa/eoa-bundle-swap-helpers.d.ts +126 -0
  164. package/dist/chains/xlayer/eoa/eoa-bundle-swap-helpers.js +228 -0
  165. package/dist/chains/xlayer/eoa/eoa-bundle-swap.d.ts +1 -95
  166. package/dist/chains/xlayer/eoa/eoa-bundle-swap.js +64 -276
  167. package/dist/chains/xlayer/eoa/eoa-wash-volume.d.ts +1 -1
  168. package/dist/chains/xlayer/eoa/eoa-wash-volume.js +14 -14
  169. package/dist/chains/xlayer/eoa/index.d.ts +10 -6
  170. package/dist/chains/xlayer/eoa/index.js +8 -23
  171. package/dist/chains/xlayer/eoa/portal-ops.js +7 -2
  172. package/dist/chains/xlayer/eoa/router-manager.js +3 -3
  173. package/dist/chains/xlayer/eoa/types.d.ts +2 -2
  174. package/dist/chains/xlayer/eoa/types.js +1 -3
  175. package/dist/contracts/helper3.d.ts +20 -17
  176. package/dist/contracts/helper3.js +56 -20
  177. package/dist/contracts/tm-bundle-helpers.d.ts +88 -0
  178. package/dist/contracts/tm-bundle-helpers.js +72 -0
  179. package/dist/contracts/tm-bundle-merkle/approve-tokenmanager.d.ts +1 -26
  180. package/dist/contracts/tm-bundle-merkle/approve-tokenmanager.js +1 -117
  181. package/dist/contracts/tm-bundle-merkle/config.d.ts +5 -70
  182. package/dist/contracts/tm-bundle-merkle/config.js +2 -115
  183. package/dist/contracts/tm-bundle-merkle/core.d.ts +1 -4
  184. package/dist/contracts/tm-bundle-merkle/core.js +1 -588
  185. package/dist/contracts/tm-bundle-merkle/index.d.ts +5 -5
  186. package/dist/contracts/tm-bundle-merkle/index.js +5 -5
  187. package/dist/contracts/tm-bundle-merkle/internal.d.ts +2 -50
  188. package/dist/contracts/tm-bundle-merkle/internal.js +2 -236
  189. package/dist/contracts/tm-bundle-merkle/pancake-proxy.d.ts +1 -28
  190. package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +1 -687
  191. package/dist/contracts/tm-bundle-merkle/private.d.ts +1 -27
  192. package/dist/contracts/tm-bundle-merkle/private.js +1 -476
  193. package/dist/contracts/tm-bundle-merkle/submit.d.ts +3 -314
  194. package/dist/contracts/tm-bundle-merkle/submit.js +3 -919
  195. package/dist/contracts/tm-bundle-merkle/swap-buy-first.d.ts +2 -55
  196. package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +2 -505
  197. package/dist/contracts/tm-bundle-merkle/swap-internal.d.ts +1 -3
  198. package/dist/contracts/tm-bundle-merkle/swap-internal.js +1 -18
  199. package/dist/contracts/tm-bundle-merkle/swap.d.ts +2 -144
  200. package/dist/contracts/tm-bundle-merkle/swap.js +2 -757
  201. package/dist/contracts/tm-bundle-merkle/types.d.ts +1 -476
  202. package/dist/contracts/tm-bundle-merkle/utils-disperse.d.ts +1 -0
  203. package/dist/contracts/tm-bundle-merkle/utils-disperse.js +1 -0
  204. package/dist/contracts/tm-bundle-merkle/utils-pairwise.d.ts +1 -0
  205. package/dist/contracts/tm-bundle-merkle/utils-pairwise.js +1 -0
  206. package/dist/contracts/tm-bundle-merkle/utils-sweep.d.ts +1 -0
  207. package/dist/contracts/tm-bundle-merkle/utils-sweep.js +1 -0
  208. package/dist/contracts/tm-bundle-merkle/utils.d.ts +5 -6
  209. package/dist/contracts/tm-bundle-merkle/utils.js +5 -6
  210. package/dist/contracts/tm-bundle.d.ts +3 -51
  211. package/dist/contracts/tm-bundle.js +102 -142
  212. package/dist/contracts/tm.d.ts +3 -2
  213. package/dist/contracts/tm.js +36 -32
  214. package/dist/contracts/tm1.js +9 -4
  215. package/dist/contracts/tm2.js +9 -4
  216. package/dist/dex/direct-router-helpers.d.ts +264 -0
  217. package/dist/dex/direct-router-helpers.js +539 -0
  218. package/dist/dex/direct-router.d.ts +3 -125
  219. package/dist/dex/direct-router.js +237 -652
  220. package/dist/dex/{direct-router/types.d.ts → types.d.ts} +1 -1
  221. package/dist/exports/root-bundle-and-tooling.d.ts +27 -0
  222. package/dist/exports/root-bundle-and-tooling.js +30 -0
  223. package/dist/exports/root-eni-and-bsc-iro.d.ts +26 -0
  224. package/dist/exports/root-eni-and-bsc-iro.js +66 -0
  225. package/dist/exports/root-foundations.d.ts +35 -0
  226. package/dist/exports/root-foundations.js +70 -0
  227. package/dist/exports/root-swap-dex-and-xlayer.d.ts +30 -0
  228. package/dist/exports/root-swap-dex-and-xlayer.js +78 -0
  229. package/dist/flap/index.d.ts +10 -0
  230. package/dist/flap/index.js +8 -0
  231. package/dist/flows/create.d.ts +2 -2
  232. package/dist/flows/create.js +6 -6
  233. package/dist/flows/index.d.ts +1 -0
  234. package/dist/flows/index.js +1 -0
  235. package/dist/index.d.ts +20 -91
  236. package/dist/index.js +20 -215
  237. package/dist/shared/abis/common.d.ts +2 -83
  238. package/dist/shared/abis/common.js +2 -252
  239. package/dist/shared/abis/index.d.ts +5 -6
  240. package/dist/shared/abis/index.js +5 -7
  241. package/dist/shared/clients/blockrazor.js +41 -24
  242. package/dist/shared/clients/club48.js +30 -26
  243. package/dist/shared/clients/emitservice.js +2 -0
  244. package/dist/shared/clients/four.js +23 -18
  245. package/dist/shared/clients/index.d.ts +8 -0
  246. package/dist/shared/clients/index.js +8 -0
  247. package/dist/shared/clients/merkle.js +26 -30
  248. package/dist/shared/constants/addresses.d.ts +1 -1
  249. package/dist/shared/constants/addresses.js +11 -2
  250. package/dist/shared/constants/chains.d.ts +1 -1
  251. package/dist/shared/constants/chains.js +1 -1
  252. package/dist/shared/constants/gas.d.ts +1 -1
  253. package/dist/shared/constants/gas.js +2 -6
  254. package/dist/shared/constants/index.d.ts +3 -0
  255. package/dist/shared/constants/index.js +1 -0
  256. package/dist/shared/constants/quote.d.ts +30 -0
  257. package/dist/shared/constants/quote.js +37 -0
  258. package/dist/shared/flap/abi.js +1 -1
  259. package/dist/shared/flap/constants.d.ts +1 -1
  260. package/dist/shared/flap/constants.js +2 -2
  261. package/dist/shared/flap/curve.js +3 -0
  262. package/dist/shared/flap/errors.d.ts +1 -4
  263. package/dist/shared/flap/errors.js +21 -3
  264. package/dist/shared/flap/index.d.ts +2 -2
  265. package/dist/shared/flap/index.js +2 -2
  266. package/dist/shared/flap/meta.d.ts +16 -18
  267. package/dist/shared/flap/meta.js +14 -26
  268. package/dist/shared/flap/permit.js +6 -5
  269. package/dist/shared/flap/pinata.d.ts +9 -2
  270. package/dist/shared/flap/pinata.js +20 -18
  271. package/dist/shared/flap/portal-bundle-merkle/config.d.ts +3 -72
  272. package/dist/shared/flap/portal-bundle-merkle/config.js +4 -124
  273. package/dist/shared/flap/portal-bundle-merkle/core-helpers.d.ts +32 -0
  274. package/dist/shared/flap/portal-bundle-merkle/core-helpers.js +83 -0
  275. package/dist/shared/flap/portal-bundle-merkle/core.d.ts +0 -4
  276. package/dist/shared/flap/portal-bundle-merkle/core.js +66 -156
  277. package/dist/shared/flap/portal-bundle-merkle/create-to-dex.js +81 -86
  278. package/dist/shared/flap/portal-bundle-merkle/curve-to-dex.js +100 -92
  279. package/dist/shared/flap/portal-bundle-merkle/index.d.ts +11 -7
  280. package/dist/shared/flap/portal-bundle-merkle/index.js +4 -7
  281. package/dist/shared/flap/portal-bundle-merkle/pancake-proxy.js +71 -68
  282. package/dist/shared/flap/portal-bundle-merkle/private.js +61 -114
  283. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first-helpers.d.ts +125 -0
  284. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first-helpers.js +113 -0
  285. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first.d.ts +1 -64
  286. package/dist/shared/flap/portal-bundle-merkle/swap-buy-first.js +66 -247
  287. package/dist/shared/flap/portal-bundle-merkle/swap-helpers.d.ts +149 -0
  288. package/dist/shared/flap/portal-bundle-merkle/swap-helpers.js +259 -0
  289. package/dist/shared/flap/portal-bundle-merkle/swap.d.ts +2 -71
  290. package/dist/shared/flap/portal-bundle-merkle/swap.js +103 -410
  291. package/dist/shared/flap/portal-bundle-merkle/types.d.ts +73 -3
  292. package/dist/shared/flap/portal-bundle-merkle/utils.d.ts +1 -80
  293. package/dist/shared/flap/portal-bundle-merkle/utils.js +145 -265
  294. package/dist/shared/flap/portal-bundle.js +54 -42
  295. package/dist/shared/flap/portal.js +32 -10
  296. package/dist/shared/flap/vanity.js +4 -7
  297. package/dist/shared/flap/vault.d.ts +1 -1
  298. package/dist/shared/flap/vault.js +54 -48
  299. package/dist/shared/foundation/dex/v3-path.d.ts +6 -0
  300. package/dist/shared/foundation/dex/v3-path.js +35 -0
  301. package/dist/shared/foundation/gas/bundle-gas.d.ts +39 -0
  302. package/dist/shared/foundation/gas/bundle-gas.js +93 -0
  303. package/dist/shared/foundation/gas/profit-hop.d.ts +20 -0
  304. package/dist/shared/foundation/gas/profit-hop.js +72 -0
  305. package/dist/shared/foundation/index.d.ts +13 -0
  306. package/dist/shared/foundation/index.js +12 -0
  307. package/dist/shared/foundation/nonce/nonce-manager.d.ts +17 -0
  308. package/dist/shared/foundation/nonce/nonce-manager.js +180 -0
  309. package/dist/shared/foundation/normalize-unknown.d.ts +9 -0
  310. package/dist/shared/foundation/normalize-unknown.js +29 -0
  311. package/dist/shared/foundation/sdk-logger.d.ts +13 -0
  312. package/dist/shared/foundation/sdk-logger.js +12 -0
  313. package/dist/shared/foundation/tx/build-request.d.ts +17 -0
  314. package/dist/shared/foundation/tx/build-request.js +25 -0
  315. package/dist/shared/foundation/tx/sign-batch.d.ts +5 -0
  316. package/dist/shared/foundation/tx/sign-batch.js +26 -0
  317. package/dist/shared/foundation/tx/wallet-sign-patch.js +18 -0
  318. package/dist/shared/foundation/types/airdrop-sweep.d.ts +79 -0
  319. package/dist/{utils/erc20/types.d.ts → shared/foundation/types/erc20.d.ts} +7 -19
  320. package/dist/{utils/holders-maker/types.d.ts → shared/foundation/types/holders-maker.d.ts} +4 -12
  321. package/dist/shared/foundation/types/index.d.ts +7 -0
  322. package/dist/{utils/lp-inspect/types.d.ts → shared/foundation/types/lp-inspect.d.ts} +4 -2
  323. package/dist/shared/foundation/types/multicall.d.ts +5 -0
  324. package/dist/shared/foundation/types/multicall.js +1 -0
  325. package/dist/shared/foundation/types/private-sale.d.ts +35 -0
  326. package/dist/shared/foundation/types/private-sale.js +1 -0
  327. package/dist/{utils/quote-helpers/types.d.ts → shared/foundation/types/quote-helpers.d.ts} +1 -0
  328. package/dist/shared/foundation/types/quote-helpers.js +1 -0
  329. package/dist/shared/four/tax-token.d.ts +1 -1
  330. package/dist/shared/four/tax-token.js +27 -7
  331. package/dist/shared/index.d.ts +6 -0
  332. package/dist/shared/index.js +4 -0
  333. package/dist/utils/airdrop-sweep.d.ts +4 -76
  334. package/dist/utils/airdrop-sweep.js +38 -52
  335. package/dist/utils/bundle-helpers.d.ts +9 -243
  336. package/dist/utils/bundle-helpers.js +10 -584
  337. package/dist/utils/constants.d.ts +5 -61
  338. package/dist/utils/constants.js +5 -80
  339. package/dist/utils/contract-factory.d.ts +2 -4
  340. package/dist/utils/contract-factory.js +25 -18
  341. package/dist/utils/erc20.d.ts +8 -90
  342. package/dist/utils/erc20.js +94 -153
  343. package/dist/utils/errors.d.ts +10 -22
  344. package/dist/utils/errors.js +61 -79
  345. package/dist/utils/holders-maker/addresses.d.ts +12 -0
  346. package/dist/utils/holders-maker/addresses.js +15 -0
  347. package/dist/utils/holders-maker/buy-tx.d.ts +44 -0
  348. package/dist/utils/holders-maker/buy-tx.js +278 -0
  349. package/dist/utils/holders-maker/constants.d.ts +6 -0
  350. package/dist/utils/holders-maker/constants.js +7 -0
  351. package/dist/utils/holders-maker/disperse.d.ts +18 -0
  352. package/dist/utils/holders-maker/disperse.js +90 -0
  353. package/dist/utils/holders-maker/routing.d.ts +4 -0
  354. package/dist/utils/holders-maker/routing.js +45 -0
  355. package/dist/utils/holders-maker/transfer-tx.d.ts +4 -0
  356. package/dist/utils/holders-maker/transfer-tx.js +67 -0
  357. package/dist/utils/holders-maker-helpers.d.ts +9 -0
  358. package/dist/utils/holders-maker-helpers.js +9 -0
  359. package/dist/utils/holders-maker.d.ts +2 -138
  360. package/dist/utils/holders-maker.js +23 -651
  361. package/dist/utils/hop-chains.d.ts +35 -0
  362. package/dist/utils/hop-chains.js +215 -0
  363. package/dist/utils/lp-inspect-helpers.d.ts +9 -0
  364. package/dist/utils/lp-inspect-helpers.js +109 -0
  365. package/dist/utils/lp-inspect.d.ts +2 -112
  366. package/dist/utils/lp-inspect.js +63 -195
  367. package/dist/utils/mpcExclusive.d.ts +2 -5
  368. package/dist/utils/mpcExclusive.js +4 -3
  369. package/dist/utils/private-sale.d.ts +2 -58
  370. package/dist/utils/private-sale.js +2 -7
  371. package/dist/utils/provider-factory.d.ts +4 -0
  372. package/dist/utils/provider-factory.js +10 -0
  373. package/dist/utils/quote-helpers.d.ts +4 -45
  374. package/dist/utils/quote-helpers.js +15 -65
  375. package/dist/utils/stealth-transfer.d.ts +2 -28
  376. package/dist/utils/stealth-transfer.js +30 -14
  377. package/dist/utils/swap-helpers.d.ts +0 -3
  378. package/dist/utils/swap-helpers.js +6 -9
  379. package/dist/utils/types/airdrop-sweep.d.ts +1 -0
  380. package/dist/utils/types/airdrop-sweep.js +1 -0
  381. package/dist/utils/types/contract-factory.d.ts +1 -0
  382. package/dist/utils/types/contract-factory.js +1 -0
  383. package/dist/utils/types/erc20.d.ts +1 -0
  384. package/dist/utils/types/erc20.js +1 -0
  385. package/dist/utils/types/errors.d.ts +1 -0
  386. package/dist/utils/types/errors.js +1 -0
  387. package/dist/utils/types/holders-maker.d.ts +1 -0
  388. package/dist/utils/types/holders-maker.js +1 -0
  389. package/dist/utils/types/hop-chains.d.ts +8 -0
  390. package/dist/utils/types/hop-chains.js +1 -0
  391. package/dist/utils/types/index.d.ts +13 -0
  392. package/dist/utils/types/index.js +1 -0
  393. package/dist/utils/types/lp-inspect.d.ts +1 -0
  394. package/dist/utils/types/lp-inspect.js +1 -0
  395. package/dist/utils/types/mpc-exclusive.d.ts +5 -0
  396. package/dist/utils/types/mpc-exclusive.js +1 -0
  397. package/dist/utils/types/private-sale.d.ts +1 -0
  398. package/dist/utils/types/private-sale.js +1 -0
  399. package/dist/utils/types/quote-helpers.d.ts +1 -0
  400. package/dist/utils/types/quote-helpers.js +1 -0
  401. package/dist/utils/types/stealth-transfer.d.ts +44 -0
  402. package/dist/utils/types/stealth-transfer.js +1 -0
  403. package/dist/utils/types/wallet.d.ts +25 -0
  404. package/dist/utils/types/wallet.js +1 -0
  405. package/dist/utils/wallet.d.ts +2 -25
  406. package/dist/utils/wallet.js +9 -10
  407. package/package.json +120 -2
  408. package/src/abis/contracts/TaxToken.json +969 -0
  409. package/src/abis/contracts/TokenManager.json +836 -0
  410. package/src/abis/contracts/TokenManager2.json +136 -0
  411. package/src/abis/contracts/TokenManagerHelper3.json +993 -0
  412. package/dist/chains/bsc/four/submit/blockrazor.d.ts +0 -18
  413. package/dist/chains/bsc/four/submit/blockrazor.js +0 -86
  414. package/dist/chains/bsc/four/submit/direct.d.ts +0 -66
  415. package/dist/chains/bsc/four/submit/direct.js +0 -452
  416. package/dist/chains/bsc/four/submit/helpers.d.ts +0 -18
  417. package/dist/chains/bsc/four/submit/helpers.js +0 -57
  418. package/dist/chains/bsc/four/submit/index.d.ts +0 -12
  419. package/dist/chains/bsc/four/submit/index.js +0 -11
  420. package/dist/chains/bsc/four/submit/merkle.d.ts +0 -18
  421. package/dist/chains/bsc/four/submit/merkle.js +0 -74
  422. package/dist/chains/bsc/four/submit/types.d.ts +0 -143
  423. package/dist/chains/bsc/four/swap/index.d.ts +0 -32
  424. package/dist/chains/bsc/four/swap/types.d.ts +0 -70
  425. package/dist/chains/bsc/four/utils/index.d.ts +0 -20
  426. package/dist/chains/bsc/four/utils/index.js +0 -1558
  427. package/dist/chains/bsc/pancake/bundle-buy-first/index.d.ts +0 -8
  428. package/dist/chains/bsc/pancake/bundle-buy-first/index.js +0 -907
  429. package/dist/chains/bsc/pancake/bundle-buy-first/types.d.ts +0 -73
  430. package/dist/chains/bsc/pancake/bundle-swap/helpers.d.ts +0 -102
  431. package/dist/chains/bsc/pancake/bundle-swap/index.d.ts +0 -50
  432. package/dist/chains/bsc/pancake/bundle-swap/index.js +0 -1066
  433. package/dist/chains/bsc/pancake/bundle-swap/types.d.ts +0 -202
  434. package/dist/chains/bsc/pancake/bundle-swap/types.js +0 -3
  435. package/dist/chains/xlayer/eip7702/bundle-swap/index.d.ts +0 -72
  436. package/dist/chains/xlayer/eip7702/bundle-swap/index.js +0 -921
  437. package/dist/chains/xlayer/eip7702/bundle-swap/types.d.ts +0 -65
  438. package/dist/chains/xlayer/eip7702/multi-hop-transfer/index.d.ts +0 -128
  439. package/dist/chains/xlayer/eip7702/multi-hop-transfer/index.js +0 -857
  440. package/dist/chains/xlayer/eip7702/volume/index.d.ts +0 -96
  441. package/dist/chains/xlayer/eip7702/volume/index.js +0 -793
  442. package/dist/dex/direct-router/index.d.ts +0 -70
  443. package/dist/dex/direct-router/index.js +0 -1410
  444. package/dist/shared/abis/TaxToken.json +0 -969
  445. package/dist/shared/abis/TokenManager.json +0 -836
  446. package/dist/shared/abis/TokenManager2.json +0 -136
  447. package/dist/shared/abis/TokenManagerHelper3.json +0 -993
  448. package/dist/shared/flap/__tests__/curve.test.js +0 -85
  449. package/dist/shared/flap/portal/index.d.ts +0 -12
  450. package/dist/shared/flap/portal/index.js +0 -11
  451. package/dist/shared/flap/portal/portal.d.ts +0 -47
  452. package/dist/shared/flap/portal/portal.js +0 -218
  453. package/dist/shared/flap/portal/types.d.ts +0 -227
  454. package/dist/shared/flap/portal/types.js +0 -80
  455. package/dist/shared/flap/portal/writer.d.ts +0 -121
  456. package/dist/shared/flap/portal/writer.js +0 -265
  457. package/dist/shared/flap/portal-bundle-merkle/core/index.d.ts +0 -18
  458. package/dist/shared/flap/portal-bundle-merkle/core/index.js +0 -938
  459. package/dist/shared/flap/portal-bundle-merkle/swap/index.d.ts +0 -42
  460. package/dist/shared/flap/portal-bundle-merkle/swap/index.js +0 -1448
  461. package/dist/shared/flap/portal-bundle-merkle/swap/types.d.ts +0 -84
  462. package/dist/shared/flap/portal-bundle-merkle/utils/index.d.ts +0 -17
  463. package/dist/shared/flap/portal-bundle-merkle/utils/index.js +0 -1024
  464. package/dist/shared/flap/portal-bundle-merkle/utils/types.d.ts +0 -16
  465. package/dist/shared 2/abis/TaxToken.json +0 -105
  466. package/dist/shared 2/abis/TokenManager.json +0 -836
  467. package/dist/shared 2/abis/TokenManager2.json +0 -60
  468. package/dist/shared 2/abis/TokenManagerHelper3.json +0 -993
  469. package/dist/shared 2/abis/common.d.ts +0 -85
  470. package/dist/shared 2/abis/common.js +0 -254
  471. package/dist/shared 2/abis/index.d.ts +0 -8
  472. package/dist/shared 2/abis/index.js +0 -8
  473. package/dist/shared 2/clients/blockrazor.d.ts +0 -314
  474. package/dist/shared 2/clients/blockrazor.js +0 -596
  475. package/dist/shared 2/clients/club48.d.ts +0 -154
  476. package/dist/shared 2/clients/club48.js +0 -331
  477. package/dist/shared 2/clients/emitservice.d.ts +0 -47
  478. package/dist/shared 2/clients/emitservice.js +0 -44
  479. package/dist/shared 2/clients/four.d.ts +0 -132
  480. package/dist/shared 2/clients/four.js +0 -281
  481. package/dist/shared 2/clients/merkle.d.ts +0 -210
  482. package/dist/shared 2/clients/merkle.js +0 -400
  483. package/dist/shared 2/flap/__tests__/curve.test.js +0 -85
  484. package/dist/shared 2/flap/abi.d.ts +0 -4
  485. package/dist/shared 2/flap/abi.js +0 -4
  486. package/dist/shared 2/flap/constants.d.ts +0 -128
  487. package/dist/shared 2/flap/constants.js +0 -143
  488. package/dist/shared 2/flap/curve.d.ts +0 -33
  489. package/dist/shared 2/flap/curve.js +0 -84
  490. package/dist/shared 2/flap/errors.d.ts +0 -37
  491. package/dist/shared 2/flap/errors.js +0 -114
  492. package/dist/shared 2/flap/index.d.ts +0 -22
  493. package/dist/shared 2/flap/index.js +0 -33
  494. package/dist/shared 2/flap/ipfs.d.ts +0 -21
  495. package/dist/shared 2/flap/ipfs.js +0 -38
  496. package/dist/shared 2/flap/meta.d.ts +0 -30
  497. package/dist/shared 2/flap/meta.js +0 -195
  498. package/dist/shared 2/flap/permit.d.ts +0 -16
  499. package/dist/shared 2/flap/permit.js +0 -67
  500. package/dist/shared 2/flap/pinata.d.ts +0 -40
  501. package/dist/shared 2/flap/pinata.js +0 -106
  502. package/dist/shared 2/flap/portal-bundle-merkle/config.d.ts +0 -79
  503. package/dist/shared 2/flap/portal-bundle-merkle/config.js +0 -133
  504. package/dist/shared 2/flap/portal-bundle-merkle/core.d.ts +0 -18
  505. package/dist/shared 2/flap/portal-bundle-merkle/core.js +0 -938
  506. package/dist/shared 2/flap/portal-bundle-merkle/create-to-dex.d.ts +0 -125
  507. package/dist/shared 2/flap/portal-bundle-merkle/create-to-dex.js +0 -665
  508. package/dist/shared 2/flap/portal-bundle-merkle/curve-to-dex.d.ts +0 -88
  509. package/dist/shared 2/flap/portal-bundle-merkle/curve-to-dex.js +0 -446
  510. package/dist/shared 2/flap/portal-bundle-merkle/index.d.ts +0 -14
  511. package/dist/shared 2/flap/portal-bundle-merkle/index.js +0 -26
  512. package/dist/shared 2/flap/portal-bundle-merkle/pancake-proxy.d.ts +0 -28
  513. package/dist/shared 2/flap/portal-bundle-merkle/private.d.ts +0 -17
  514. package/dist/shared 2/flap/portal-bundle-merkle/private.js +0 -549
  515. package/dist/shared 2/flap/portal-bundle-merkle/swap-buy-first.d.ts +0 -65
  516. package/dist/shared 2/flap/portal-bundle-merkle/swap-buy-first.js +0 -831
  517. package/dist/shared 2/flap/portal-bundle-merkle/swap.d.ts +0 -201
  518. package/dist/shared 2/flap/portal-bundle-merkle/swap.js +0 -1359
  519. package/dist/shared 2/flap/portal-bundle-merkle/types.d.ts +0 -358
  520. package/dist/shared 2/flap/portal-bundle-merkle/utils.d.ts +0 -89
  521. package/dist/shared 2/flap/portal-bundle-merkle/utils.js +0 -963
  522. package/dist/shared 2/flap/portal-bundle.d.ts +0 -119
  523. package/dist/shared 2/flap/portal-bundle.js +0 -584
  524. package/dist/shared 2/flap/portal.d.ts +0 -392
  525. package/dist/shared 2/flap/portal.js +0 -559
  526. package/dist/shared 2/flap/vanity.d.ts +0 -48
  527. package/dist/shared 2/flap/vanity.js +0 -110
  528. package/dist/shared 2/flap/vault.d.ts +0 -240
  529. package/dist/shared 2/flap/vault.js +0 -366
  530. package/dist/shared 2/four/index.d.ts +0 -7
  531. package/dist/shared 2/four/index.js +0 -22
  532. package/dist/shared 2/four/tax-token.d.ts +0 -176
  533. package/dist/shared 2/four/tax-token.js +0 -302
  534. package/dist/shared 2/index.d.ts +0 -10
  535. package/dist/shared 2/index.js +0 -10
  536. package/dist/utils/__tests__/errors.test.js +0 -76
  537. package/dist/utils/erc20/index.d.ts +0 -242
  538. package/dist/utils/erc20/index.js +0 -645
  539. package/dist/utils/holders-maker/helpers.d.ts +0 -43
  540. package/dist/utils/holders-maker/helpers.js +0 -371
  541. package/dist/utils/holders-maker/index.d.ts +0 -26
  542. package/dist/utils/holders-maker/index.js +0 -218
  543. package/dist/utils/holders-maker/types.js +0 -4
  544. package/dist/utils/lp-inspect/index.d.ts +0 -44
  545. package/dist/utils/lp-inspect/index.js +0 -937
  546. package/dist/utils/quote-helpers/index.d.ts +0 -107
  547. package/dist/utils/quote-helpers/index.js +0 -346
  548. /package/dist/{chains/bsc/four/submit/types.js → __tests__/subpath-exports.test.d.ts} +0 -0
  549. /package/dist/{chains/bsc/four/swap/types.js → bundle-core/__tests__/config-helpers.test.d.ts} +0 -0
  550. /package/dist/{chains/bsc/four/utils/types.d.ts → bundle-core/__tests__/facade-parity.test.d.ts} +0 -0
  551. /package/dist/{chains/bsc/four/utils/types.js → bundle-core/__tests__/sign-context-helpers.test.d.ts} +0 -0
  552. /package/dist/{chains/bsc/pancake/bundle-buy-first/types.js → bundle-core/__tests__/sign-fixture.test.d.ts} +0 -0
  553. /package/dist/{chains/xlayer/eip7702/multi-hop-transfer/types.js → bundle-core/four-meme/types/buy-first.js} +0 -0
  554. /package/dist/{chains/xlayer/eip7702/volume/types.js → bundle-core/four-meme/types/core-flow.js} +0 -0
  555. /package/dist/{dex/direct-router/types.js → bundle-core/four-meme/types/index.js} +0 -0
  556. /package/dist/{shared 2/flap/__tests__/curve.test.d.ts → bundle-core/four-meme/types/swap-internal.js} +0 -0
  557. /package/dist/{chains/xlayer/eip7702/bundle-swap → bundle-core/four-meme}/types.js +0 -0
  558. /package/dist/{shared/flap/__tests__/curve.test.d.ts → bundle-core/types/index.js} +0 -0
  559. /package/dist/{shared 2/flap/portal-bundle-merkle → bundle-core}/types.js +0 -0
  560. /package/dist/{shared/flap/portal-bundle-merkle/core/types.d.ts → chains/xlayer/eip7702/multi-hop-transfer-helpers.js} +0 -0
  561. /package/dist/{shared/flap/portal-bundle-merkle/core → dex}/types.js +0 -0
  562. /package/dist/shared/{flap/portal-bundle-merkle/swap/types.js → foundation/tx/wallet-sign-patch.d.ts} +0 -0
  563. /package/dist/shared/{flap/portal-bundle-merkle/utils/types.js → foundation/types/airdrop-sweep.js} +0 -0
  564. /package/dist/{utils/__tests__/errors.test.d.ts → shared/foundation/types/erc20.js} +0 -0
  565. /package/dist/{utils/erc20/types.js → shared/foundation/types/holders-maker.js} +0 -0
  566. /package/dist/{utils/lp-inspect/types.js → shared/foundation/types/index.js} +0 -0
  567. /package/dist/{utils/quote-helpers/types.js → shared/foundation/types/lp-inspect.js} +0 -0
@@ -1,1024 +0,0 @@
1
- import { ethers, Wallet } from 'ethers';
2
- import { getOptimizedGasPrice, NonceManager, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../../../utils/bundle-helpers.js';
3
- import { ADDRESSES } from '../../../../utils/constants.js';
4
- import { GAS_LIMITS, PROFIT_CONFIG, calculateTransferFee } from '../../../constants/index.js';
5
- import { MULTICALL3_ABI, ERC20_BALANCE_ABI } from '../../../abis/common.js';
6
- import { getTxType, getGasPriceConfig, shouldExtractProfit, getProfitRecipient } from '../config.js';
7
- // ==================== 类型定义 ====================
8
- fromPrivateKey: string;
9
- recipients: string[];
10
- amount ? : string;
11
- amounts ? : string[];
12
- tokenAddress ? : string;
13
- tokenDecimals ? : number;
14
- hopCount ? : number | number[];
15
- hopPrivateKeys ? : string[][];
16
- items ? : {
17
- recipient: string,
18
- amount: string | bigint,
19
- hopCount: number,
20
- hopPrivateKeys: string[]
21
- }[];
22
- config: FlapSignConfig;
23
- startNonce ? : number;
24
- ;
25
- hopWallets ? : (string | GeneratedWallet)[][]; // ✅ 转账多跳钱包(兼容旧版 string[][] 和新版 GeneratedWallet[][])
26
- profitHopWallets ? : GeneratedWallet[]; // ✅ 利润多跳钱包
27
- metadata ? : {
28
- totalAmount: string,
29
- profitAmount: string,
30
- profitRecipient: string,
31
- recipientCount: number,
32
- isNative: boolean,
33
- tokenAddress: string
34
- };
35
- ;
36
- sourcePrivateKeys: string[];
37
- target: string;
38
- ratioPct ? : number;
39
- ratios ? : number[];
40
- amount ? : string;
41
- amounts ? : string[];
42
- tokenAddress ? : string;
43
- tokenDecimals ? : number;
44
- skipIfInsufficient ? : boolean;
45
- hopCount ? : number | number[];
46
- hopPrivateKeys ? : string[][];
47
- sources ? : {
48
- privateKey: string,
49
- ratioPct: number,
50
- amount: string,
51
- hopCount: number,
52
- hopPrivateKeys: string[]
53
- }[];
54
- config: FlapSignConfig;
55
- startNonce ? : number;
56
- ;
57
- hopWallets ? : (string | GeneratedWallet)[][]; // ✅ 转账多跳钱包(兼容旧版 string[][] 和新版 GeneratedWallet[][])
58
- profitHopWallets ? : GeneratedWallet[]; // ✅ 利润多跳钱包
59
- metadata ? : {
60
- totalAmount: string,
61
- profitAmount: string,
62
- profitRecipient: string,
63
- sourceCount: number,
64
- isNative: boolean,
65
- tokenAddress: string
66
- };
67
- ;
68
- // ==================== 链配置 ====================
69
- const CHAIN_ID_MAP = {
70
- 'BSC': 56,
71
- 'MONAD': 143,
72
- 'XLAYER': 196
73
- };
74
- // ==================== 链常量 ====================
75
- // ✅ 使用公共模块
76
- const MULTICALL3_ADDRESS = ADDRESSES.BSC.Multicall3;
77
- // ==================== 内部辅助函数 ====================
78
- const decimalsCache = new Map();
79
- async function getErc20Decimals(provider, token) {
80
- const network = await provider.getNetwork();
81
- const key = `${network.chainId}_${token.toLowerCase()}`;
82
- if (decimalsCache.has(key))
83
- return decimalsCache.get(key);
84
- try {
85
- const erc20 = new ethers.Contract(token, ['function decimals() view returns (uint8)'], provider);
86
- const d = await erc20.decimals();
87
- if (!Number.isFinite(d) || d < 0 || d > 36)
88
- return 18;
89
- decimalsCache.set(key, d);
90
- return d;
91
- }
92
- catch {
93
- return 18;
94
- }
95
- }
96
- /**
97
- * ✅ 生成多跳中间钱包(返回完整钱包信息:地址 + 私钥)
98
- */
99
- function generateHopWallets(recipientCount, hopCount) {
100
- const hopCounts = Array.isArray(hopCount) ? hopCount : new Array(recipientCount).fill(hopCount);
101
- if (hopCounts.every(h => h <= 0))
102
- return null;
103
- const result = [];
104
- for (let i = 0; i < recipientCount; i++) {
105
- const chain = [];
106
- for (let j = 0; j < hopCounts[i]; j++) {
107
- const wallet = Wallet.createRandom();
108
- chain.push({
109
- address: wallet.address,
110
- privateKey: wallet.privateKey
111
- });
112
- }
113
- result.push(chain);
114
- }
115
- return result;
116
- }
117
- function normalizeAmounts(recipients, amount, amounts) {
118
- if (amounts && amounts.length > 0) {
119
- if (amounts.length !== recipients.length) {
120
- throw new Error(`amounts length (${amounts.length}) must match recipients length (${recipients.length})`);
121
- }
122
- return amounts;
123
- }
124
- if (amount !== undefined && amount.trim().length > 0) {
125
- return new Array(recipients.length).fill(amount);
126
- }
127
- throw new Error('Either amount or amounts must be provided');
128
- }
129
- async function batchGetBalances(provider, addresses, tokenAddress) {
130
- if (addresses.length === 0)
131
- return [];
132
- if (!tokenAddress) {
133
- return Promise.all(addresses.map(addr => provider.getBalance(addr).catch(() => 0n)));
134
- }
135
- else {
136
- // ✅ 使用公共模块
137
- const multicall = new ethers.Contract(MULTICALL3_ADDRESS, MULTICALL3_ABI, provider);
138
- const iface = new ethers.Interface(ERC20_BALANCE_ABI);
139
- const calls = addresses.map(addr => ({
140
- target: tokenAddress,
141
- allowFailure: true,
142
- callData: iface.encodeFunctionData('balanceOf', [addr])
143
- }));
144
- try {
145
- const results = await multicall.aggregate3(calls);
146
- return results.map((result) => {
147
- if (result.success) {
148
- return iface.decodeFunctionResult('balanceOf', result.returnData)[0];
149
- }
150
- return 0n;
151
- });
152
- }
153
- catch {
154
- const fallbackCalls = addresses.map(addr => provider
155
- .call({ to: tokenAddress, data: iface.encodeFunctionData('balanceOf', [addr]) })
156
- .then(raw => iface.decodeFunctionResult('balanceOf', raw)[0])
157
- .catch(() => 0n));
158
- return Promise.all(fallbackCalls);
159
- }
160
- }
161
- }
162
- /**
163
- * 计算 Gas Limit
164
- * - 原生代币转账:21000 gas(固定)
165
- * - ERC20 标准 transfer:约 45000-55000 gas,使用 55000 作为安全值
166
- *
167
- * ✅ 优化:降低 ERC20 gas limit,减少中转钱包 BNB 残留
168
- */
169
- function calculateGasLimit(config, isNative, hasHops, _hopCount = 0) {
170
- if (config.gasLimit !== undefined) {
171
- return BigInt(config.gasLimit);
172
- }
173
- // ✅ 原生代币: 21000, ERC20 标准 transfer: 48000(USDT 最低约 46815)
174
- const baseGas = isNative ? 21000 : 48000;
175
- // ✅ 多跳时每个中转钱包只执行一笔 transfer,使用较小的安全系数
176
- const multiplier = config.gasLimitMultiplier ?? 1.1;
177
- return BigInt(Math.ceil(baseGas * multiplier));
178
- }
179
- function isNativeTokenAddress(tokenAddress) {
180
- if (!tokenAddress)
181
- return true;
182
- const v = tokenAddress.trim().toLowerCase();
183
- if (!v)
184
- return true;
185
- if (v === 'native')
186
- return true;
187
- if (v === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee')
188
- return true;
189
- return false;
190
- }
191
- // ==================== 分散函数 ====================
192
- /**
193
- * Flap Protocol: 分散(仅签名版本)
194
- * ✅ 支持利润提取(按地址数量收取固定费用)
195
- * ✅ 支持多跳
196
- * ✅ 支持 Multicall3 批量获取余额
197
- */
198
- export async function flapDisperseWithBundleMerkle(params) {
199
- const { chain, fromPrivateKey, recipients, amount, amounts, tokenAddress, tokenDecimals, hopCount = 0, hopPrivateKeys, items, config, startNonce } = params;
200
- if (!recipients || recipients.length === 0) {
201
- return { signedTransactions: [], hopWallets: undefined };
202
- }
203
- const chainIdNum = CHAIN_ID_MAP[chain] ?? 56;
204
- const provider = new ethers.JsonRpcProvider(config.rpcUrl, { chainId: chainIdNum, name: chain });
205
- const mainWallet = new Wallet(fromPrivateKey, provider);
206
- const isNative = isNativeTokenAddress(tokenAddress);
207
- const txType = getTxType(config);
208
- // 预处理数据
209
- const normalizedAmounts = items && items.length > 0
210
- ? items.map(it => (typeof it.amount === 'bigint' ? it.amount.toString() : String(it.amount)))
211
- : normalizeAmounts(recipients, amount, amounts);
212
- const providedHops = (() => {
213
- if (hopPrivateKeys && hopPrivateKeys.length > 0) {
214
- if (hopPrivateKeys.length !== recipients.length) {
215
- throw new Error(`hopPrivateKeys length (${hopPrivateKeys.length}) must match recipients length (${recipients.length})`);
216
- }
217
- return hopPrivateKeys.every(h => h.length === 0) ? null : hopPrivateKeys;
218
- }
219
- if (items && items.length > 0) {
220
- const hops = items.map(it => it.hopPrivateKeys ?? []);
221
- return hops.every(h => h.length === 0) ? null : hops;
222
- }
223
- return null;
224
- })();
225
- const hopCountInput = (() => {
226
- if (items && items.length > 0) {
227
- const baseArray = Array.isArray(hopCount) ? hopCount : new Array(recipients.length).fill(hopCount);
228
- return items.map((it, i) => (typeof it.hopCount === 'number' ? it.hopCount : (baseArray[i] ?? 0)));
229
- }
230
- return hopCount;
231
- })();
232
- const preparedHops = providedHops ?? generateHopWallets(recipients.length, hopCountInput);
233
- const hasHops = preparedHops !== null;
234
- const maxHopCount = hasHops ? Math.max(...preparedHops.map(h => h.length)) : 0;
235
- const finalGasLimit = calculateGasLimit(config, isNative, hasHops, maxHopCount);
236
- const nativeGasLimit = GAS_LIMITS.BRIBE;
237
- const signedTxs = [];
238
- const extractProfit = shouldExtractProfit(config);
239
- const profitAddr = getProfitRecipient();
240
- let totalProfit = 0n;
241
- let totalAmountBeforeProfit = 0n;
242
- let profitHopWallets; // ✅ 收集利润多跳钱包
243
- const nonceManager = new NonceManager(provider);
244
- if (!preparedHops) {
245
- // ========== 无多跳:直接批量转账 ==========
246
- const extraTxCount = extractProfit ? 1 : 0;
247
- const totalTxCount = recipients.length + extraTxCount;
248
- const [gasPrice, nonces] = await Promise.all([
249
- getOptimizedGasPrice(provider, getGasPriceConfig(config)),
250
- startNonce !== undefined
251
- ? Promise.resolve(Array.from({ length: totalTxCount }, (_, i) => startNonce + i))
252
- : nonceManager.getNextNonceBatch(mainWallet, totalTxCount)
253
- ]);
254
- // ✅ 按地址数量收取固定费用(原生代币)
255
- if (extractProfit) {
256
- totalProfit = calculateTransferFee(chainIdNum, recipients.length);
257
- console.log(`[flap disperse] 利润按地址数量收取: ${ethers.formatEther(totalProfit)} 原生币 (${recipients.length} 地址)`);
258
- }
259
- if (isNative) {
260
- const txDataList = recipients.map((to, i) => {
261
- const originalAmount = ethers.parseEther(normalizedAmounts[i]);
262
- totalAmountBeforeProfit += originalAmount;
263
- // ✅ 不再从转账金额中扣除利润,全额转账
264
- return { to, value: originalAmount, nonce: nonces[i] };
265
- });
266
- const txPromises = txDataList.map(({ to, value, nonce }) => mainWallet.signTransaction({
267
- to,
268
- value,
269
- nonce,
270
- gasPrice,
271
- gasLimit: nativeGasLimit,
272
- chainId: chainIdNum,
273
- type: txType
274
- }));
275
- signedTxs.push(...(await Promise.all(txPromises)));
276
- }
277
- else {
278
- const decimals = tokenDecimals ?? (await getErc20Decimals(provider, tokenAddress));
279
- const iface = new ethers.Interface(['function transfer(address,uint256) returns (bool)']);
280
- const txDataList = recipients.map((to, i) => {
281
- const originalAmount = ethers.parseUnits(normalizedAmounts[i], decimals);
282
- totalAmountBeforeProfit += originalAmount;
283
- // ✅ 不再从转账金额中扣除利润,全额转账
284
- const data = iface.encodeFunctionData('transfer', [to, originalAmount]);
285
- return { data, nonce: nonces[i] };
286
- });
287
- const txPromises = txDataList.map(({ data, nonce }) => mainWallet.signTransaction({
288
- to: tokenAddress,
289
- data,
290
- value: 0n,
291
- nonce,
292
- gasPrice,
293
- gasLimit: finalGasLimit,
294
- chainId: chainIdNum,
295
- type: txType
296
- }));
297
- signedTxs.push(...(await Promise.all(txPromises)));
298
- }
299
- // ✅ 利润多跳转账(固定费用,原生代币)
300
- if (extractProfit && totalProfit > 0n) {
301
- const profitHopResult = await buildProfitHopTransactions({
302
- provider,
303
- payerWallet: mainWallet,
304
- profitAmount: totalProfit,
305
- profitRecipient: profitAddr,
306
- hopCount: PROFIT_HOP_COUNT,
307
- gasPrice,
308
- chainId: chainIdNum,
309
- txType,
310
- startNonce: nonces[recipients.length]
311
- });
312
- signedTxs.push(...profitHopResult.signedTransactions);
313
- profitHopWallets = profitHopResult.hopWallets;
314
- }
315
- }
316
- else {
317
- // ========== 有多跳:构建跳转链 ==========
318
- const [gasPrice, decimals] = await Promise.all([
319
- getOptimizedGasPrice(provider, getGasPriceConfig(config)),
320
- isNative ? Promise.resolve(18) : Promise.resolve(tokenDecimals ?? await getErc20Decimals(provider, tokenAddress))
321
- ]);
322
- const iface = isNative ? null : new ethers.Interface(['function transfer(address,uint256) returns (bool)']);
323
- const gasFeePerHop = finalGasLimit * gasPrice;
324
- let mainWalletNonceCount = 0;
325
- for (let i = 0; i < recipients.length; i++) {
326
- const hopChain = preparedHops[i];
327
- if (hopChain.length === 0) {
328
- mainWalletNonceCount += 1;
329
- }
330
- else {
331
- const nonceNeed = isNative ? 1 : (hopChain.length + 1);
332
- mainWalletNonceCount += nonceNeed;
333
- }
334
- }
335
- if (extractProfit)
336
- mainWalletNonceCount += 1;
337
- const allMainNonces = startNonce !== undefined
338
- ? Array.from({ length: mainWalletNonceCount }, (_, i) => startNonce + i)
339
- : await nonceManager.getNextNonceBatch(mainWallet, mainWalletNonceCount);
340
- let mainNonceIdx = 0;
341
- const txsToSign = [];
342
- // ✅ 按地址数量收取固定费用(原生代币)
343
- if (extractProfit) {
344
- totalProfit = calculateTransferFee(chainIdNum, recipients.length);
345
- console.log(`[flap disperse hops] 利润按地址数量收取: ${ethers.formatEther(totalProfit)} 原生币 (${recipients.length} 地址)`);
346
- }
347
- for (let i = 0; i < recipients.length; i++) {
348
- const finalRecipient = recipients[i];
349
- const originalAmountWei = isNative
350
- ? ethers.parseEther(normalizedAmounts[i])
351
- : ethers.parseUnits(normalizedAmounts[i], decimals);
352
- totalAmountBeforeProfit += originalAmountWei;
353
- // ✅ 不再从转账金额中扣除利润,全额转账
354
- const amountWei = originalAmountWei;
355
- const hopChain = preparedHops[i];
356
- if (hopChain.length === 0) {
357
- const nonce = allMainNonces[mainNonceIdx++];
358
- if (isNative) {
359
- txsToSign.push({
360
- wallet: mainWallet,
361
- tx: { to: finalRecipient, value: amountWei, nonce, gasPrice, gasLimit: nativeGasLimit, chainId: chainIdNum, type: txType }
362
- });
363
- }
364
- else {
365
- const data = iface.encodeFunctionData('transfer', [finalRecipient, amountWei]);
366
- txsToSign.push({
367
- wallet: mainWallet,
368
- tx: { to: tokenAddress, data, value: 0n, nonce, gasPrice, gasLimit: finalGasLimit, chainId: chainIdNum, type: txType }
369
- });
370
- }
371
- continue;
372
- }
373
- // ✅ 支持 string 和 GeneratedWallet 两种类型
374
- const fullChain = [mainWallet, ...hopChain.map(w => new Wallet(typeof w === 'string' ? w : w.privateKey, provider))];
375
- const addresses = [...fullChain.map(w => w.address), finalRecipient];
376
- if (!isNative) {
377
- for (let j = 0; j < hopChain.length; j++) {
378
- const nonce = allMainNonces[mainNonceIdx++];
379
- txsToSign.push({
380
- wallet: mainWallet,
381
- tx: { to: fullChain[j + 1].address, value: gasFeePerHop, nonce, gasPrice, gasLimit: nativeGasLimit, chainId: chainIdNum, type: txType }
382
- });
383
- }
384
- }
385
- for (let j = 0; j < addresses.length - 1; j++) {
386
- const fromWallet = fullChain[j];
387
- const toAddress = addresses[j + 1];
388
- const nonce = j === 0 ? allMainNonces[mainNonceIdx++] : 0;
389
- if (isNative) {
390
- const remainingHops = addresses.length - 2 - j;
391
- const additionalGas = gasFeePerHop * BigInt(remainingHops);
392
- const transferValue = amountWei + additionalGas;
393
- txsToSign.push({
394
- wallet: fromWallet,
395
- tx: { to: toAddress, value: transferValue, nonce, gasPrice, gasLimit: finalGasLimit, chainId: chainIdNum, type: txType }
396
- });
397
- }
398
- else {
399
- const data = iface.encodeFunctionData('transfer', [toAddress, amountWei]);
400
- txsToSign.push({
401
- wallet: fromWallet,
402
- tx: { to: tokenAddress, data, value: 0n, nonce, gasPrice, gasLimit: finalGasLimit, chainId: chainIdNum, type: txType }
403
- });
404
- }
405
- }
406
- }
407
- const signedTxsResult = await Promise.all(txsToSign.map(({ wallet, tx }) => wallet.signTransaction(tx)));
408
- signedTxs.push(...signedTxsResult);
409
- // ✅ 利润多跳转账(固定费用,原生代币)
410
- if (extractProfit && totalProfit > 0n) {
411
- const profitNonce = allMainNonces[mainNonceIdx++];
412
- const profitHopResult = await buildProfitHopTransactions({
413
- provider,
414
- payerWallet: mainWallet,
415
- profitAmount: totalProfit,
416
- profitRecipient: profitAddr,
417
- hopCount: PROFIT_HOP_COUNT,
418
- gasPrice,
419
- chainId: chainIdNum,
420
- txType,
421
- startNonce: profitNonce
422
- });
423
- signedTxs.push(...profitHopResult.signedTransactions);
424
- profitHopWallets = profitHopResult.hopWallets;
425
- }
426
- }
427
- return {
428
- signedTransactions: signedTxs,
429
- hopWallets: preparedHops || undefined,
430
- profitHopWallets, // ✅ 返回利润多跳钱包
431
- metadata: extractProfit ? {
432
- totalAmount: ethers.formatEther(totalAmountBeforeProfit),
433
- profitAmount: ethers.formatEther(totalProfit),
434
- profitRecipient: profitAddr,
435
- recipientCount: recipients.length,
436
- isNative,
437
- tokenAddress: isNative ? undefined : tokenAddress
438
- } : undefined
439
- };
440
- }
441
- // ==================== 归集函数 ====================
442
- /**
443
- * Flap Protocol: 归集(仅签名版本)
444
- * ✅ 支持利润提取(按地址数量收取固定费用)
445
- * ✅ 查询余额最大的钱包支付利润
446
- * ✅ 支持多跳
447
- * ✅ 支持 Multicall3 批量获取余额
448
- */
449
- export async function flapSweepWithBundleMerkle(params) {
450
- const { chain, sourcePrivateKeys, target, ratioPct, ratios, amount, amounts, tokenAddress, tokenDecimals, skipIfInsufficient = true, hopCount = 0, hopPrivateKeys, sources, config } = params;
451
- if (!sourcePrivateKeys || sourcePrivateKeys.length === 0) {
452
- return { signedTransactions: [], hopWallets: undefined };
453
- }
454
- const chainIdNum = CHAIN_ID_MAP[chain] ?? 56;
455
- const provider = new ethers.JsonRpcProvider(config.rpcUrl, { chainId: chainIdNum, name: chain });
456
- const isNative = isNativeTokenAddress(tokenAddress);
457
- const txType = getTxType(config);
458
- const clamp = (n) => (typeof n === 'number' && Number.isFinite(n)
459
- ? Math.max(0, Math.min(100, Math.floor(n)))
460
- : undefined);
461
- const ratio = clamp(ratioPct);
462
- const actualKeys = (() => {
463
- if (sources && sources.length > 0)
464
- return sources.map(s => s.privateKey);
465
- return sourcePrivateKeys;
466
- })();
467
- const providedHops = (() => {
468
- if (hopPrivateKeys && hopPrivateKeys.length > 0) {
469
- if (hopPrivateKeys.length !== actualKeys.length) {
470
- throw new Error(`hopPrivateKeys length (${hopPrivateKeys.length}) must match sourcePrivateKeys length (${actualKeys.length})`);
471
- }
472
- return hopPrivateKeys.every(h => h.length === 0) ? null : hopPrivateKeys;
473
- }
474
- if (sources && sources.length > 0) {
475
- const hops = sources.map(s => s.hopPrivateKeys ?? []);
476
- return hops.every(h => h.length === 0) ? null : hops;
477
- }
478
- return null;
479
- })();
480
- const hopCountInput = (() => {
481
- if (sources && sources.length > 0) {
482
- const baseArray = Array.isArray(hopCount) ? hopCount : new Array(actualKeys.length).fill(hopCount);
483
- return sources.map((s, i) => (typeof s.hopCount === 'number' ? s.hopCount : (baseArray[i] ?? 0)));
484
- }
485
- return hopCount;
486
- })();
487
- const preparedHops = providedHops ?? generateHopWallets(actualKeys.length, hopCountInput);
488
- const hasHops = preparedHops !== null;
489
- const maxHopCount = hasHops ? Math.max(...preparedHops.map(h => h.length)) : 0;
490
- const finalGasLimit = calculateGasLimit(config, isNative, hasHops, maxHopCount);
491
- const nativeGasLimit = GAS_LIMITS.BRIBE;
492
- const signedTxs = [];
493
- const extractProfit = shouldExtractProfit(config);
494
- const profitAddr = getProfitRecipient();
495
- let totalProfit = 0n;
496
- let totalAmountBeforeProfit = 0n;
497
- let profitHopWallets; // ✅ 收集利润多跳钱包
498
- if (!preparedHops) {
499
- // ========== 无多跳:直接批量归集 ==========
500
- const wallets = actualKeys.map(pk => new Wallet(pk, provider));
501
- const addresses = wallets.map(w => w.address);
502
- const nonceManager = new NonceManager(provider);
503
- // ✅ 按地址数量收取固定费用(原生代币)
504
- if (extractProfit) {
505
- totalProfit = calculateTransferFee(chainIdNum, wallets.length);
506
- console.log(`[flap sweep] 利润按地址数量收取: ${ethers.formatEther(totalProfit)} 原生币 (${wallets.length} 地址)`);
507
- }
508
- if (isNative) {
509
- const [gasPrice, balances] = await Promise.all([
510
- getOptimizedGasPrice(provider, getGasPriceConfig(config)),
511
- batchGetBalances(provider, addresses)
512
- ]);
513
- const gasCostBase = nativeGasLimit * gasPrice;
514
- const profitTxGas = PROFIT_CONFIG.HOP.GAS_LIMIT * gasPrice * BigInt(PROFIT_HOP_COUNT + 1);
515
- // 第一步:计算所有钱包的归集金额,找出余额最大的钱包
516
- const sweepAmounts = [];
517
- let maxSweepIndex = -1;
518
- let maxSweepAmount = 0n;
519
- for (let i = 0; i < wallets.length; i++) {
520
- const bal = balances[i];
521
- let toSend = 0n;
522
- const ratioForI = (() => {
523
- if (sources && sources[i] && sources[i].ratioPct !== undefined)
524
- return clamp(sources[i].ratioPct);
525
- if (ratios && ratios[i] !== undefined)
526
- return clamp(ratios[i]);
527
- return ratio;
528
- })();
529
- const amountStrForI = (() => {
530
- if (sources && sources[i] && sources[i].amount !== undefined)
531
- return String(sources[i].amount);
532
- if (amounts && amounts[i] !== undefined)
533
- return String(amounts[i]);
534
- return amount !== undefined ? String(amount) : undefined;
535
- })();
536
- const gasCost = gasCostBase;
537
- if (ratioForI !== undefined) {
538
- const want = (bal * BigInt(ratioForI)) / 100n;
539
- const maxSendable = bal > gasCost ? (bal - gasCost) : 0n;
540
- toSend = want > maxSendable ? maxSendable : want;
541
- }
542
- else if (amountStrForI && amountStrForI.trim().length > 0) {
543
- const amt = ethers.parseEther(amountStrForI);
544
- const need = amt + gasCost;
545
- if (!skipIfInsufficient || bal >= need)
546
- toSend = amt;
547
- }
548
- sweepAmounts.push(toSend);
549
- totalAmountBeforeProfit += toSend;
550
- // ✅ 找出余额最大的钱包作为利润支付者
551
- if (toSend > maxSweepAmount) {
552
- maxSweepAmount = toSend;
553
- maxSweepIndex = i;
554
- }
555
- }
556
- // 检查支付者余额是否足够支付利润
557
- if (extractProfit && totalProfit > 0n && maxSweepIndex >= 0) {
558
- const payerBalance = balances[maxSweepIndex];
559
- const payerSweepAmount = sweepAmounts[maxSweepIndex];
560
- const payerNeedGas = gasCostBase + profitTxGas;
561
- if (payerBalance < payerSweepAmount + payerNeedGas + totalProfit) {
562
- // 余额不足支付利润,减少归集金额
563
- const maxPayerSweep = payerBalance > (payerNeedGas + totalProfit) ? payerBalance - payerNeedGas - totalProfit : 0n;
564
- sweepAmounts[maxSweepIndex] = maxPayerSweep;
565
- totalAmountBeforeProfit = sweepAmounts.reduce((sum, amt) => sum + amt, 0n);
566
- }
567
- }
568
- // 第二步:生成归集交易
569
- let payerProfitNonce;
570
- if (extractProfit && totalProfit > 0n && maxSweepIndex >= 0) {
571
- const payerWallet = wallets[maxSweepIndex];
572
- const nonces = await nonceManager.getNextNonceBatch(payerWallet, 2);
573
- payerProfitNonce = nonces[1];
574
- }
575
- const walletsToSweep = wallets.filter((_, i) => sweepAmounts[i] > 0n && i !== maxSweepIndex);
576
- const nonces = walletsToSweep.length > 0
577
- ? await nonceManager.getNextNoncesForWallets(walletsToSweep)
578
- : [];
579
- let nonceIdx = 0;
580
- const txPromises = wallets.map(async (w, i) => {
581
- const toSend = sweepAmounts[i];
582
- if (toSend <= 0n)
583
- return null;
584
- // ✅ 全额归集,不从转账金额中扣除利润
585
- let nonce;
586
- if (i === maxSweepIndex && payerProfitNonce !== undefined) {
587
- nonce = payerProfitNonce - 1;
588
- }
589
- else {
590
- nonce = nonces[nonceIdx++];
591
- }
592
- const mainTx = await w.signTransaction({
593
- to: target,
594
- value: toSend,
595
- nonce,
596
- gasPrice,
597
- gasLimit: nativeGasLimit,
598
- chainId: chainIdNum,
599
- type: txType
600
- });
601
- return mainTx;
602
- });
603
- const allTxs = (await Promise.all(txPromises)).filter(tx => tx !== null);
604
- signedTxs.push(...allTxs);
605
- // ✅ 利润多跳转账(固定费用,原生代币)
606
- if (extractProfit && totalProfit > 0n && maxSweepIndex >= 0 && payerProfitNonce !== undefined) {
607
- const payerWallet = wallets[maxSweepIndex];
608
- const profitHopResult = await buildProfitHopTransactions({
609
- provider,
610
- payerWallet,
611
- profitAmount: totalProfit,
612
- profitRecipient: profitAddr,
613
- hopCount: PROFIT_HOP_COUNT,
614
- gasPrice,
615
- chainId: chainIdNum,
616
- txType,
617
- startNonce: payerProfitNonce
618
- });
619
- signedTxs.push(...profitHopResult.signedTransactions);
620
- profitHopWallets = profitHopResult.hopWallets;
621
- }
622
- }
623
- else {
624
- // ERC20 归集
625
- const [gasPrice, decimals, balances, nativeBalances] = await Promise.all([
626
- getOptimizedGasPrice(provider, getGasPriceConfig(config)),
627
- Promise.resolve(tokenDecimals ?? await getErc20Decimals(provider, tokenAddress)),
628
- batchGetBalances(provider, addresses, tokenAddress),
629
- batchGetBalances(provider, addresses)
630
- ]);
631
- const iface = new ethers.Interface(['function transfer(address,uint256) returns (bool)']);
632
- const profitTxGas = PROFIT_CONFIG.HOP.GAS_LIMIT * gasPrice * BigInt(PROFIT_HOP_COUNT + 1);
633
- const sweepAmounts = [];
634
- let maxSweepIndex = -1;
635
- let maxSweepAmount = 0n;
636
- for (let i = 0; i < wallets.length; i++) {
637
- const bal = balances[i];
638
- let toSend = 0n;
639
- const ratioForI = (() => {
640
- if (sources && sources[i] && sources[i].ratioPct !== undefined)
641
- return clamp(sources[i].ratioPct);
642
- if (ratios && ratios[i] !== undefined)
643
- return clamp(ratios[i]);
644
- return ratio;
645
- })();
646
- const amountStrForI = (() => {
647
- if (sources && sources[i] && sources[i].amount !== undefined)
648
- return String(sources[i].amount);
649
- if (amounts && amounts[i] !== undefined)
650
- return String(amounts[i]);
651
- return amount !== undefined ? String(amount) : undefined;
652
- })();
653
- if (ratioForI !== undefined) {
654
- toSend = (bal * BigInt(ratioForI)) / 100n;
655
- }
656
- else if (amountStrForI && amountStrForI.trim().length > 0) {
657
- toSend = ethers.parseUnits(amountStrForI, decimals);
658
- }
659
- if (toSend <= 0n || (skipIfInsufficient && bal < toSend)) {
660
- sweepAmounts.push(0n);
661
- continue;
662
- }
663
- const totalGasNeeded = finalGasLimit * gasPrice;
664
- const nativeBal = nativeBalances[i] ?? 0n;
665
- if (skipIfInsufficient && nativeBal < totalGasNeeded) {
666
- sweepAmounts.push(0n);
667
- continue;
668
- }
669
- sweepAmounts.push(toSend);
670
- totalAmountBeforeProfit += toSend;
671
- // ✅ 找出原生代币余额最大的钱包作为利润支付者
672
- if (nativeBal > maxSweepAmount) {
673
- maxSweepAmount = nativeBal;
674
- maxSweepIndex = i;
675
- }
676
- }
677
- // 检查支付者原生代币余额是否足够支付固定费用
678
- if (extractProfit && totalProfit > 0n && maxSweepIndex >= 0) {
679
- const payerNativeBalance = nativeBalances[maxSweepIndex] ?? 0n;
680
- const payerNeedGas = finalGasLimit * gasPrice + profitTxGas + totalProfit;
681
- if (payerNativeBalance < payerNeedGas) {
682
- // 余额不足,跳过利润收取
683
- totalProfit = 0n;
684
- }
685
- }
686
- let payerProfitNonce;
687
- if (extractProfit && totalProfit > 0n && maxSweepIndex >= 0) {
688
- const payerWallet = wallets[maxSweepIndex];
689
- const nonces = await nonceManager.getNextNonceBatch(payerWallet, 2);
690
- payerProfitNonce = nonces[1];
691
- }
692
- const walletsToSweepErc20 = wallets.filter((_, i) => sweepAmounts[i] > 0n && i !== maxSweepIndex);
693
- const noncesErc20 = walletsToSweepErc20.length > 0
694
- ? await nonceManager.getNextNoncesForWallets(walletsToSweepErc20)
695
- : [];
696
- let nonceIdxErc20 = 0;
697
- const txPromises = wallets.map(async (w, i) => {
698
- const toSend = sweepAmounts[i];
699
- if (toSend <= 0n)
700
- return null;
701
- let nonce;
702
- if (i === maxSweepIndex && payerProfitNonce !== undefined) {
703
- nonce = payerProfitNonce - 1;
704
- }
705
- else {
706
- nonce = noncesErc20[nonceIdxErc20++];
707
- }
708
- // ✅ 全额归集 ERC20,不从转账金额中扣除利润
709
- const data = iface.encodeFunctionData('transfer', [target, toSend]);
710
- const mainTx = await w.signTransaction({
711
- to: tokenAddress,
712
- data,
713
- value: 0n,
714
- nonce,
715
- gasPrice,
716
- gasLimit: finalGasLimit,
717
- chainId: chainIdNum,
718
- type: txType
719
- });
720
- return mainTx;
721
- });
722
- const allTxs = (await Promise.all(txPromises)).filter(tx => tx !== null);
723
- signedTxs.push(...allTxs);
724
- // ✅ 利润多跳转账(固定费用,原生代币)
725
- if (extractProfit && totalProfit > 0n && maxSweepIndex >= 0 && payerProfitNonce !== undefined) {
726
- const payerWallet = wallets[maxSweepIndex];
727
- const profitHopResult = await buildProfitHopTransactions({
728
- provider,
729
- payerWallet,
730
- profitAmount: totalProfit,
731
- profitRecipient: profitAddr,
732
- hopCount: PROFIT_HOP_COUNT,
733
- gasPrice,
734
- chainId: chainIdNum,
735
- txType,
736
- startNonce: payerProfitNonce
737
- });
738
- signedTxs.push(...profitHopResult.signedTransactions);
739
- profitHopWallets = profitHopResult.hopWallets;
740
- }
741
- }
742
- }
743
- else {
744
- // ========== 有多跳:构建跳转链归集 ==========
745
- const sourceWallets = actualKeys.map(pk => new Wallet(pk, provider));
746
- // ✅ 按地址数量收取固定费用(原生代币)
747
- if (extractProfit) {
748
- totalProfit = calculateTransferFee(chainIdNum, sourceWallets.length);
749
- console.log(`[flap sweep hops] 利润按地址数量收取: ${ethers.formatEther(totalProfit)} 原生币 (${sourceWallets.length} 地址)`);
750
- }
751
- const withHopIndexes = [];
752
- const withoutHopIndexes = [];
753
- for (let i = 0; i < preparedHops.length; i++) {
754
- if (preparedHops[i].length > 0) {
755
- withHopIndexes.push(i);
756
- }
757
- else {
758
- withoutHopIndexes.push(i);
759
- }
760
- }
761
- const sourceAddresses = sourceWallets.map(w => w.address);
762
- const [gasPrice, decimals, balances, nativeBalances] = await Promise.all([
763
- getOptimizedGasPrice(provider, getGasPriceConfig(config)),
764
- isNative ? Promise.resolve(18) : Promise.resolve(tokenDecimals ?? await getErc20Decimals(provider, tokenAddress)),
765
- batchGetBalances(provider, sourceAddresses, tokenAddress),
766
- isNative ? Promise.resolve([]) : batchGetBalances(provider, sourceAddresses)
767
- ]);
768
- const iface = isNative ? null : new ethers.Interface(['function transfer(address,uint256) returns (bool)']);
769
- const gasFeePerHop = finalGasLimit * gasPrice;
770
- const nonceManager = new NonceManager(provider);
771
- const sweepAmounts = new Array(sourceWallets.length).fill(0n);
772
- // 处理无跳转的地址
773
- for (const i of withoutHopIndexes) {
774
- const sourceWallet = sourceWallets[i];
775
- const bal = balances[i];
776
- let toSend = 0n;
777
- if (isNative) {
778
- const gasCost = nativeGasLimit * gasPrice;
779
- const ratioForI = (() => {
780
- if (sources && sources[i] && sources[i].ratioPct !== undefined)
781
- return clamp(sources[i].ratioPct);
782
- if (ratios && ratios[i] !== undefined)
783
- return clamp(ratios[i]);
784
- return ratio;
785
- })();
786
- const amountStrForI = (() => {
787
- if (sources && sources[i] && sources[i].amount !== undefined)
788
- return String(sources[i].amount);
789
- if (amounts && amounts[i] !== undefined)
790
- return String(amounts[i]);
791
- return amount !== undefined ? String(amount) : undefined;
792
- })();
793
- if (ratioForI !== undefined) {
794
- const want = (bal * BigInt(ratioForI)) / 100n;
795
- const maxSendable = bal > gasCost ? (bal - gasCost) : 0n;
796
- toSend = want > maxSendable ? maxSendable : want;
797
- }
798
- else if (amountStrForI && amountStrForI.trim().length > 0) {
799
- const amt = ethers.parseEther(amountStrForI);
800
- const need = amt + gasCost;
801
- if (!skipIfInsufficient || bal >= need)
802
- toSend = amt;
803
- }
804
- if (toSend > 0n) {
805
- sweepAmounts[i] = toSend;
806
- totalAmountBeforeProfit += toSend;
807
- const nonce = await nonceManager.getNextNonce(sourceWallet);
808
- const tx = await sourceWallet.signTransaction({
809
- to: target,
810
- value: toSend,
811
- nonce,
812
- gasPrice,
813
- gasLimit: nativeGasLimit,
814
- chainId: chainIdNum,
815
- type: txType
816
- });
817
- signedTxs.push(tx);
818
- }
819
- }
820
- else {
821
- const ratioForI = (() => {
822
- if (sources && sources[i] && sources[i].ratioPct !== undefined)
823
- return clamp(sources[i].ratioPct);
824
- if (ratios && ratios[i] !== undefined)
825
- return clamp(ratios[i]);
826
- return ratio;
827
- })();
828
- const amountStrForI = (() => {
829
- if (sources && sources[i] && sources[i].amount !== undefined)
830
- return String(sources[i].amount);
831
- if (amounts && amounts[i] !== undefined)
832
- return String(amounts[i]);
833
- return amount !== undefined ? String(amount) : undefined;
834
- })();
835
- if (ratioForI !== undefined) {
836
- toSend = (bal * BigInt(ratioForI)) / 100n;
837
- }
838
- else if (amountStrForI && amountStrForI.trim().length > 0) {
839
- toSend = ethers.parseUnits(amountStrForI, decimals);
840
- }
841
- if (toSend > 0n && (!skipIfInsufficient || bal >= toSend)) {
842
- sweepAmounts[i] = toSend;
843
- totalAmountBeforeProfit += toSend;
844
- const nonce = await nonceManager.getNextNonce(sourceWallet);
845
- const data = iface.encodeFunctionData('transfer', [target, toSend]);
846
- const tx = await sourceWallet.signTransaction({
847
- to: tokenAddress,
848
- data,
849
- value: 0n,
850
- nonce,
851
- gasPrice,
852
- gasLimit: finalGasLimit,
853
- chainId: chainIdNum,
854
- type: txType
855
- });
856
- signedTxs.push(tx);
857
- }
858
- }
859
- }
860
- // 处理有跳转的地址
861
- for (const i of withHopIndexes) {
862
- const sourceWallet = sourceWallets[i];
863
- const hopChain = preparedHops[i];
864
- let toSend = 0n;
865
- const bal = balances[i];
866
- if (isNative) {
867
- const totalGasCost = finalGasLimit * gasPrice * BigInt(hopChain.length + 1);
868
- const ratioForI = (() => {
869
- if (sources && sources[i] && sources[i].ratioPct !== undefined)
870
- return clamp(sources[i].ratioPct);
871
- if (ratios && ratios[i] !== undefined)
872
- return clamp(ratios[i]);
873
- return ratio;
874
- })();
875
- const amountStrForI = (() => {
876
- if (sources && sources[i] && sources[i].amount !== undefined)
877
- return String(sources[i].amount);
878
- if (amounts && amounts[i] !== undefined)
879
- return String(amounts[i]);
880
- return amount !== undefined ? String(amount) : undefined;
881
- })();
882
- if (ratioForI !== undefined) {
883
- const want = (bal * BigInt(ratioForI)) / 100n;
884
- const maxSendable = bal > totalGasCost ? (bal - totalGasCost) : 0n;
885
- toSend = want > maxSendable ? maxSendable : want;
886
- }
887
- else if (amountStrForI && amountStrForI.trim().length > 0) {
888
- const amt = ethers.parseEther(amountStrForI);
889
- const need = amt + totalGasCost;
890
- if (!skipIfInsufficient || bal >= need)
891
- toSend = amt;
892
- }
893
- }
894
- else {
895
- const nativeBal = nativeBalances[i];
896
- const nativeNeeded = (gasFeePerHop * BigInt(hopChain.length)) + (finalGasLimit * gasPrice);
897
- if (nativeBal < nativeNeeded && skipIfInsufficient)
898
- continue;
899
- const ratioForI = (() => {
900
- if (sources && sources[i] && sources[i].ratioPct !== undefined)
901
- return clamp(sources[i].ratioPct);
902
- if (ratios && ratios[i] !== undefined)
903
- return clamp(ratios[i]);
904
- return ratio;
905
- })();
906
- const amountStrForI = (() => {
907
- if (sources && sources[i] && sources[i].amount !== undefined)
908
- return String(sources[i].amount);
909
- if (amounts && amounts[i] !== undefined)
910
- return String(amounts[i]);
911
- return amount !== undefined ? String(amount) : undefined;
912
- })();
913
- if (ratioForI !== undefined) {
914
- toSend = (bal * BigInt(ratioForI)) / 100n;
915
- }
916
- else if (amountStrForI && amountStrForI.trim().length > 0) {
917
- toSend = ethers.parseUnits(amountStrForI, decimals);
918
- }
919
- if (skipIfInsufficient && bal < toSend)
920
- toSend = 0n;
921
- }
922
- if (toSend <= 0n)
923
- continue;
924
- sweepAmounts[i] = toSend;
925
- totalAmountBeforeProfit += toSend;
926
- // ✅ 支持 string 和 GeneratedWallet 两种类型
927
- const fullChain = [sourceWallet, ...hopChain.map(w => new Wallet(typeof w === 'string' ? w : w.privateKey, provider))];
928
- const addresses = [...fullChain.map(w => w.address), target];
929
- if (!isNative) {
930
- const gasNonces = await nonceManager.getNextNonceBatch(sourceWallet, hopChain.length);
931
- for (let j = 0; j < hopChain.length; j++) {
932
- const tx = await sourceWallet.signTransaction({
933
- to: fullChain[j + 1].address,
934
- value: gasFeePerHop,
935
- nonce: gasNonces[j],
936
- gasPrice,
937
- gasLimit: nativeGasLimit,
938
- chainId: chainIdNum,
939
- type: txType
940
- });
941
- signedTxs.push(tx);
942
- }
943
- }
944
- for (let j = 0; j < addresses.length - 1; j++) {
945
- const fromWallet = fullChain[j];
946
- const toAddress = addresses[j + 1];
947
- const nonce = j === 0
948
- ? await nonceManager.getNextNonce(sourceWallet)
949
- : 0;
950
- if (isNative) {
951
- const remainingHops = addresses.length - 2 - j;
952
- const additionalGas = gasFeePerHop * BigInt(remainingHops);
953
- const valueToTransfer = toSend + additionalGas;
954
- const tx = await fromWallet.signTransaction({
955
- to: toAddress,
956
- value: valueToTransfer,
957
- nonce,
958
- gasPrice,
959
- gasLimit: finalGasLimit,
960
- chainId: chainIdNum,
961
- type: txType
962
- });
963
- signedTxs.push(tx);
964
- }
965
- else {
966
- const data = iface.encodeFunctionData('transfer', [toAddress, toSend]);
967
- const tx = await fromWallet.signTransaction({
968
- to: tokenAddress,
969
- data,
970
- value: 0n,
971
- nonce,
972
- gasPrice,
973
- gasLimit: finalGasLimit,
974
- chainId: chainIdNum,
975
- type: txType
976
- });
977
- signedTxs.push(tx);
978
- }
979
- }
980
- }
981
- // ✅ 利润多跳转账(固定费用,原生代币)- totalProfit 已在函数开头计算
982
- if (extractProfit && totalProfit > 0n && totalAmountBeforeProfit > 0n) {
983
- // 找出余额最大的钱包作为利润支付者
984
- let maxSweepIndex = -1;
985
- let maxSweepAmount = 0n;
986
- for (let i = 0; i < sweepAmounts.length; i++) {
987
- if (sweepAmounts[i] > maxSweepAmount) {
988
- maxSweepAmount = sweepAmounts[i];
989
- maxSweepIndex = i;
990
- }
991
- }
992
- if (maxSweepIndex >= 0) {
993
- const payerWallet = sourceWallets[maxSweepIndex];
994
- const profitNonce = await nonceManager.getNextNonce(payerWallet);
995
- const profitHopResult = await buildProfitHopTransactions({
996
- provider,
997
- payerWallet,
998
- profitAmount: totalProfit,
999
- profitRecipient: profitAddr,
1000
- hopCount: PROFIT_HOP_COUNT,
1001
- gasPrice,
1002
- chainId: chainIdNum,
1003
- txType,
1004
- startNonce: profitNonce
1005
- });
1006
- signedTxs.push(...profitHopResult.signedTransactions);
1007
- profitHopWallets = profitHopResult.hopWallets;
1008
- }
1009
- }
1010
- }
1011
- return {
1012
- signedTransactions: signedTxs,
1013
- hopWallets: preparedHops || undefined,
1014
- profitHopWallets, // ✅ 返回利润多跳钱包
1015
- metadata: extractProfit ? {
1016
- totalAmount: isNative ? ethers.formatEther(totalAmountBeforeProfit) : ethers.formatUnits(totalAmountBeforeProfit, tokenDecimals ?? 18),
1017
- profitAmount: ethers.formatEther(totalProfit),
1018
- profitRecipient: profitAddr,
1019
- sourceCount: actualKeys.length,
1020
- isNative,
1021
- tokenAddress: isNative ? undefined : tokenAddress
1022
- } : undefined
1023
- };
1024
- }