four-flap-meme-sdk 1.9.49 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +41 -6
- package/README.md +31 -0
- package/README.zh-CN.md +41 -6
- package/dist/abis/common.js +74 -68
- package/dist/abis/flap/vault.js +9 -7
- package/dist/abis/index.d.ts +3 -4
- package/dist/abis/index.js +3 -4
- package/dist/bundle-core/__tests__/config-helpers.test.js +28 -0
- package/dist/bundle-core/__tests__/facade-parity.test.js +33 -0
- package/dist/bundle-core/__tests__/sign-context-helpers.test.d.ts +1 -0
- package/dist/bundle-core/__tests__/sign-context-helpers.test.js +60 -0
- package/dist/bundle-core/__tests__/sign-fixture.test.d.ts +1 -0
- package/dist/bundle-core/__tests__/sign-fixture.test.js +220 -0
- package/dist/bundle-core/__tests__/sign-fixtures.d.ts +10 -0
- package/dist/bundle-core/__tests__/sign-fixtures.js +16 -0
- package/dist/bundle-core/config-helpers.d.ts +36 -0
- package/dist/bundle-core/config-helpers.js +57 -0
- package/dist/bundle-core/errors.d.ts +50 -0
- package/dist/bundle-core/errors.js +34 -0
- package/dist/bundle-core/four-meme/approve-tokenmanager.d.ts +7 -0
- package/dist/bundle-core/four-meme/approve-tokenmanager.js +99 -0
- package/dist/bundle-core/four-meme/core-helpers.d.ts +8 -0
- package/dist/bundle-core/four-meme/core-helpers.js +40 -0
- package/dist/bundle-core/four-meme/core.d.ts +4 -0
- package/dist/bundle-core/four-meme/core.js +515 -0
- package/dist/bundle-core/four-meme/pancake-proxy.d.ts +28 -0
- package/dist/bundle-core/four-meme/pancake-proxy.js +679 -0
- package/dist/bundle-core/four-meme/private.d.ts +27 -0
- package/dist/bundle-core/four-meme/private.js +465 -0
- package/dist/bundle-core/four-meme/sign-context-helpers.d.ts +2 -0
- package/dist/bundle-core/four-meme/sign-context-helpers.js +2 -0
- package/dist/bundle-core/four-meme/swap-buy-first.d.ts +8 -0
- package/dist/bundle-core/four-meme/swap-buy-first.js +493 -0
- package/dist/bundle-core/four-meme/swap-hop-helpers.d.ts +6 -0
- package/dist/bundle-core/four-meme/swap-hop-helpers.js +63 -0
- package/dist/bundle-core/four-meme/swap-internal.d.ts +3 -0
- package/dist/bundle-core/four-meme/swap-internal.js +18 -0
- package/dist/bundle-core/four-meme/swap-sign-helpers.d.ts +27 -0
- package/dist/bundle-core/four-meme/swap-sign-helpers.js +105 -0
- package/dist/bundle-core/four-meme/swap.d.ts +17 -0
- package/dist/bundle-core/four-meme/swap.js +505 -0
- package/dist/bundle-core/four-meme/types/buy-first.d.ts +50 -0
- package/dist/bundle-core/four-meme/types/buy-first.js +1 -0
- package/dist/bundle-core/four-meme/types/core-flow.d.ts +63 -0
- package/dist/bundle-core/four-meme/types/core-flow.js +1 -0
- package/dist/bundle-core/four-meme/types/index.d.ts +600 -0
- package/dist/bundle-core/four-meme/types/index.js +1 -0
- package/dist/bundle-core/four-meme/types/swap-internal.d.ts +19 -0
- package/dist/bundle-core/four-meme/types/swap-internal.js +1 -0
- package/dist/bundle-core/four-meme/types.d.ts +1 -0
- package/dist/bundle-core/four-meme/types.js +1 -0
- package/dist/bundle-core/four-meme/utils-disperse.d.ts +7 -0
- package/dist/bundle-core/four-meme/utils-disperse.js +396 -0
- package/dist/bundle-core/four-meme/utils-pairwise.d.ts +8 -0
- package/dist/bundle-core/four-meme/utils-pairwise.js +328 -0
- package/dist/bundle-core/four-meme/utils-sweep.d.ts +8 -0
- package/dist/bundle-core/four-meme/utils-sweep.js +744 -0
- package/dist/bundle-core/index.d.ts +8 -0
- package/dist/bundle-core/index.js +8 -0
- package/dist/bundle-core/internal.d.ts +21 -0
- package/dist/bundle-core/internal.js +182 -0
- package/dist/bundle-core/sign-context-helpers.d.ts +25 -0
- package/dist/bundle-core/sign-context-helpers.js +67 -0
- package/dist/bundle-core/submit.d.ts +293 -0
- package/dist/bundle-core/submit.js +727 -0
- package/dist/bundle-core/types/index.d.ts +8 -0
- package/dist/bundle-core/types/index.js +1 -0
- package/dist/bundle-core/types.d.ts +1 -0
- package/dist/bundle-core/types.js +1 -0
- package/dist/chains/bsc/four/approve-tokenmanager.d.ts +1 -26
- package/dist/chains/bsc/four/approve-tokenmanager.js +1 -116
- package/dist/chains/bsc/four/config.d.ts +5 -70
- package/dist/chains/bsc/four/config.js +2 -115
- package/dist/chains/bsc/four/core.d.ts +1 -4
- package/dist/chains/bsc/four/core.js +1 -589
- package/dist/chains/bsc/four/disperse.d.ts +12 -0
- package/dist/chains/bsc/four/disperse.js +470 -0
- package/dist/chains/bsc/four/index.d.ts +6 -6
- package/dist/chains/bsc/four/index.js +6 -6
- package/dist/chains/bsc/four/internal.d.ts +2 -50
- package/dist/chains/bsc/four/internal.js +2 -237
- package/dist/chains/bsc/four/pairwise.d.ts +7 -0
- package/dist/chains/bsc/four/pairwise.js +308 -0
- package/dist/chains/bsc/four/pancake-proxy.d.ts +1 -28
- package/dist/chains/bsc/four/pancake-proxy.js +1 -688
- package/dist/chains/bsc/four/private.d.ts +1 -27
- package/dist/chains/bsc/four/private.js +1 -477
- package/dist/chains/bsc/four/submit.d.ts +2 -315
- package/dist/chains/bsc/four/submit.js +2 -746
- package/dist/chains/bsc/four/swap-buy-first.d.ts +2 -55
- package/dist/chains/bsc/four/swap-buy-first.js +2 -506
- package/dist/chains/bsc/four/swap-internal.d.ts +1 -3
- package/dist/chains/bsc/four/swap-internal.js +1 -18
- package/dist/chains/bsc/four/swap.d.ts +2 -144
- package/dist/chains/bsc/four/swap.js +2 -760
- package/dist/chains/bsc/four/sweep.d.ts +13 -0
- package/dist/chains/bsc/four/sweep.js +788 -0
- package/dist/chains/bsc/four/types.d.ts +1 -476
- package/dist/chains/bsc/four/utils-disperse.d.ts +1 -0
- package/dist/chains/bsc/four/utils-disperse.js +1 -0
- package/dist/chains/bsc/four/utils-pairwise.d.ts +1 -0
- package/dist/chains/bsc/four/utils-pairwise.js +1 -0
- package/dist/chains/bsc/four/utils-sweep.d.ts +1 -0
- package/dist/chains/bsc/four/utils-sweep.js +1 -0
- package/dist/chains/bsc/four/utils.d.ts +5 -18
- package/dist/chains/bsc/four/utils.js +5 -1534
- package/dist/chains/bsc/pancake/bundle-buy-first-helpers.d.ts +159 -0
- package/dist/chains/bsc/pancake/bundle-buy-first-helpers.js +117 -0
- package/dist/chains/bsc/pancake/bundle-buy-first.d.ts +1 -91
- package/dist/chains/bsc/pancake/bundle-buy-first.js +97 -207
- package/dist/chains/bsc/pancake/bundle-swap-helpers.d.ts +241 -0
- package/dist/chains/bsc/pancake/bundle-swap-helpers.js +565 -0
- package/dist/chains/bsc/pancake/bundle-swap.d.ts +1 -79
- package/dist/chains/bsc/pancake/bundle-swap.js +111 -686
- package/dist/chains/bsc/pancake/index.d.ts +4 -2
- package/dist/chains/bsc/pancake/index.js +1 -3
- package/dist/chains/bsc/platforms/iro/factory.js +3 -1
- package/dist/chains/bsc/platforms/iro/index.d.ts +5 -5
- package/dist/chains/bsc/platforms/iro/index.js +3 -3
- package/dist/chains/bsc/platforms/iro/pool.js +31 -10
- package/dist/chains/bsc/platforms/iro/token.js +4 -1
- package/dist/chains/eni/batch-router/bundle-approve.js +4 -3
- package/dist/chains/eni/batch-router/transfer.js +54 -23
- package/dist/chains/eni/batch-router/utils.js +32 -6
- package/dist/chains/eni/bundler/sign.js +4 -4
- package/dist/chains/eni/bundler/submit.js +1 -4
- package/dist/chains/eni/constants.js +1 -1
- package/dist/chains/eni/index.d.ts +1 -1
- package/dist/chains/eni/platforms/daoaas/create.js +2 -2
- package/dist/chains/eni/platforms/daoaas/index.d.ts +3 -3
- package/dist/chains/eni/platforms/daoaas/index.js +3 -3
- package/dist/chains/eni/platforms/daoaas/meta.js +8 -4
- package/dist/chains/eni/platforms/daoaas/portal-direct.js +28 -43
- package/dist/chains/eni/platforms/daoaas/portal.js +10 -6
- package/dist/chains/eni/platforms/dswap/liquidity.js +58 -26
- package/dist/chains/eni/platforms/fair-launch/index.d.ts +2 -2
- package/dist/chains/eni/platforms/fair-launch/index.js +1 -1
- package/dist/chains/eni/platforms/fair-launch/launcher.js +87 -47
- package/dist/chains/eni/platforms/fair-launch/pool.js +4 -1
- package/dist/chains/eni/platforms/fair-launch/presets.js +2 -2
- package/dist/chains/eni/platforms/iro/factory.js +3 -1
- package/dist/chains/eni/platforms/iro/index.d.ts +6 -6
- package/dist/chains/eni/platforms/iro/index.js +4 -4
- package/dist/chains/eni/platforms/iro/pool.js +90 -26
- package/dist/chains/eni/platforms/iro/token.js +107 -31
- package/dist/chains/eni/platforms/iro/whitelist.js +6 -18
- package/dist/chains/eni/submit.js +5 -13
- package/dist/chains/xlayer/eip7702/bundle-approve.d.ts +2 -26
- package/dist/chains/xlayer/eip7702/bundle-approve.js +11 -20
- package/dist/chains/xlayer/eip7702/bundle-buy.d.ts +2 -6
- package/dist/chains/xlayer/eip7702/bundle-buy.js +13 -51
- package/dist/chains/xlayer/eip7702/bundle-create.js +93 -56
- package/dist/chains/xlayer/eip7702/bundle-sell.d.ts +2 -6
- package/dist/chains/xlayer/eip7702/bundle-sell.js +26 -74
- package/dist/chains/xlayer/eip7702/bundle-swap.d.ts +3 -65
- package/dist/chains/xlayer/eip7702/bundle-swap.js +51 -68
- package/dist/chains/xlayer/eip7702/constants.d.ts +1 -16
- package/dist/chains/xlayer/eip7702/constants.js +3 -21
- package/dist/chains/xlayer/eip7702/index.d.ts +27 -46
- package/dist/chains/xlayer/eip7702/index.js +27 -81
- package/dist/chains/xlayer/eip7702/multi-hop-transfer-helpers.d.ts +79 -0
- package/dist/chains/xlayer/eip7702/multi-hop-transfer-helpers.js +1 -0
- package/dist/chains/xlayer/eip7702/multi-hop-transfer.d.ts +2 -203
- package/dist/chains/xlayer/eip7702/multi-hop-transfer.js +58 -291
- package/dist/chains/xlayer/eip7702/transfer-context-helpers.d.ts +26 -0
- package/dist/chains/xlayer/eip7702/transfer-context-helpers.js +57 -0
- package/dist/chains/xlayer/eip7702/types.d.ts +88 -0
- package/dist/chains/xlayer/eip7702/utils.d.ts +0 -3
- package/dist/chains/xlayer/eip7702/utils.js +23 -28
- package/dist/chains/xlayer/eip7702/volume-helpers.d.ts +148 -0
- package/dist/chains/xlayer/eip7702/volume-helpers.js +48 -0
- package/dist/chains/xlayer/eip7702/volume.d.ts +6 -184
- package/dist/chains/xlayer/eip7702/volume.js +83 -158
- package/dist/chains/xlayer/eoa/constants.js +1 -1
- package/dist/chains/xlayer/eoa/dex-helpers.js +5 -5
- package/dist/chains/xlayer/eoa/eoa-bundle-swap-helpers.d.ts +126 -0
- package/dist/chains/xlayer/eoa/eoa-bundle-swap-helpers.js +228 -0
- package/dist/chains/xlayer/eoa/eoa-bundle-swap.d.ts +1 -95
- package/dist/chains/xlayer/eoa/eoa-bundle-swap.js +64 -276
- package/dist/chains/xlayer/eoa/eoa-wash-volume.d.ts +1 -1
- package/dist/chains/xlayer/eoa/eoa-wash-volume.js +14 -14
- package/dist/chains/xlayer/eoa/index.d.ts +10 -6
- package/dist/chains/xlayer/eoa/index.js +8 -23
- package/dist/chains/xlayer/eoa/portal-ops.js +7 -2
- package/dist/chains/xlayer/eoa/router-manager.js +3 -3
- package/dist/chains/xlayer/eoa/types-core.d.ts +363 -0
- package/dist/chains/xlayer/eoa/types-core.js +53 -0
- package/dist/chains/xlayer/eoa/types-create.d.ts +413 -0
- package/dist/chains/xlayer/eoa/types-create.js +9 -0
- package/dist/chains/xlayer/eoa/types-volume.d.ts +209 -0
- package/dist/chains/xlayer/eoa/types-volume.js +13 -0
- package/dist/chains/xlayer/eoa/types.d.ts +2 -2
- package/dist/chains/xlayer/eoa/types.js +1 -3
- package/dist/contracts/helper3.d.ts +20 -17
- package/dist/contracts/helper3.js +56 -20
- package/dist/contracts/tm-bundle-helpers.d.ts +88 -0
- package/dist/contracts/tm-bundle-helpers.js +72 -0
- package/dist/contracts/tm-bundle-merkle/approve-tokenmanager.d.ts +1 -26
- package/dist/contracts/tm-bundle-merkle/approve-tokenmanager.js +1 -117
- package/dist/contracts/tm-bundle-merkle/config.d.ts +5 -70
- package/dist/contracts/tm-bundle-merkle/config.js +2 -115
- package/dist/contracts/tm-bundle-merkle/core.d.ts +1 -4
- package/dist/contracts/tm-bundle-merkle/core.js +1 -588
- package/dist/contracts/tm-bundle-merkle/index.d.ts +5 -5
- package/dist/contracts/tm-bundle-merkle/index.js +5 -5
- package/dist/contracts/tm-bundle-merkle/internal.d.ts +2 -50
- package/dist/contracts/tm-bundle-merkle/internal.js +2 -236
- package/dist/contracts/tm-bundle-merkle/pancake-proxy.d.ts +1 -28
- package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +1 -687
- package/dist/contracts/tm-bundle-merkle/private.d.ts +1 -27
- package/dist/contracts/tm-bundle-merkle/private.js +1 -476
- package/dist/contracts/tm-bundle-merkle/submit.d.ts +3 -314
- package/dist/contracts/tm-bundle-merkle/submit.js +3 -919
- package/dist/contracts/tm-bundle-merkle/swap-buy-first.d.ts +2 -55
- package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +2 -505
- package/dist/contracts/tm-bundle-merkle/swap-internal.d.ts +1 -3
- package/dist/contracts/tm-bundle-merkle/swap-internal.js +1 -18
- package/dist/contracts/tm-bundle-merkle/swap.d.ts +2 -144
- package/dist/contracts/tm-bundle-merkle/swap.js +2 -757
- package/dist/contracts/tm-bundle-merkle/types.d.ts +1 -476
- package/dist/contracts/tm-bundle-merkle/utils-disperse.d.ts +1 -0
- package/dist/contracts/tm-bundle-merkle/utils-disperse.js +1 -0
- package/dist/contracts/tm-bundle-merkle/utils-pairwise.d.ts +1 -0
- package/dist/contracts/tm-bundle-merkle/utils-pairwise.js +1 -0
- package/dist/contracts/tm-bundle-merkle/utils-sweep.d.ts +1 -0
- package/dist/contracts/tm-bundle-merkle/utils-sweep.js +1 -0
- package/dist/contracts/tm-bundle-merkle/utils.d.ts +5 -6
- package/dist/contracts/tm-bundle-merkle/utils.js +5 -6
- package/dist/contracts/tm-bundle.d.ts +3 -51
- package/dist/contracts/tm-bundle.js +102 -142
- package/dist/contracts/tm.d.ts +3 -2
- package/dist/contracts/tm.js +36 -32
- package/dist/contracts/tm1.js +9 -4
- package/dist/contracts/tm2.js +9 -4
- package/dist/dex/direct-router-helpers.d.ts +264 -0
- package/dist/dex/direct-router-helpers.js +539 -0
- package/dist/dex/direct-router.d.ts +3 -125
- package/dist/dex/direct-router.js +237 -652
- package/dist/dex/types.d.ts +81 -0
- package/dist/dex/types.js +1 -0
- package/dist/exports/root-bundle-and-tooling.d.ts +27 -0
- package/dist/exports/root-bundle-and-tooling.js +30 -0
- package/dist/exports/root-eni-and-bsc-iro.d.ts +26 -0
- package/dist/exports/root-eni-and-bsc-iro.js +66 -0
- package/dist/exports/root-foundations.d.ts +35 -0
- package/dist/exports/root-foundations.js +70 -0
- package/dist/exports/root-swap-dex-and-xlayer.d.ts +30 -0
- package/dist/exports/root-swap-dex-and-xlayer.js +78 -0
- package/dist/flows/create.d.ts +2 -2
- package/dist/flows/create.js +6 -6
- package/dist/flows/index.d.ts +1 -0
- package/dist/flows/index.js +1 -0
- package/dist/index.d.ts +20 -91
- package/dist/index.js +20 -215
- package/dist/shared/abis/common.d.ts +2 -83
- package/dist/shared/abis/common.js +2 -252
- package/dist/shared/abis/index.d.ts +5 -6
- package/dist/shared/abis/index.js +5 -7
- package/dist/shared/clients/blockrazor.js +41 -24
- package/dist/shared/clients/club48.js +30 -26
- package/dist/shared/clients/emitservice.js +2 -0
- package/dist/shared/clients/four.js +23 -18
- package/dist/shared/clients/index.d.ts +8 -0
- package/dist/shared/clients/index.js +8 -0
- package/dist/shared/clients/merkle.js +26 -30
- package/dist/shared/constants/addresses.d.ts +1 -1
- package/dist/shared/constants/addresses.js +11 -2
- package/dist/shared/constants/chains.d.ts +1 -1
- package/dist/shared/constants/chains.js +1 -1
- package/dist/shared/constants/gas.d.ts +1 -1
- package/dist/shared/constants/gas.js +2 -6
- package/dist/shared/constants/index.d.ts +1 -0
- package/dist/shared/constants/index.js +1 -0
- package/dist/shared/constants/quote.d.ts +30 -0
- package/dist/shared/constants/quote.js +37 -0
- package/dist/shared/flap/__tests__/curve.test.js +3 -3
- package/dist/shared/flap/abi.js +1 -1
- package/dist/shared/flap/constants.d.ts +1 -1
- package/dist/shared/flap/constants.js +2 -2
- package/dist/shared/flap/curve.js +3 -0
- package/dist/shared/flap/errors.d.ts +1 -4
- package/dist/shared/flap/errors.js +21 -3
- package/dist/shared/flap/index.d.ts +2 -2
- package/dist/shared/flap/index.js +2 -2
- package/dist/shared/flap/meta.d.ts +16 -18
- package/dist/shared/flap/meta.js +14 -26
- package/dist/shared/flap/permit.js +6 -5
- package/dist/shared/flap/pinata.d.ts +9 -2
- package/dist/shared/flap/pinata.js +20 -18
- package/dist/shared/flap/portal-bundle-merkle/config.d.ts +3 -72
- package/dist/shared/flap/portal-bundle-merkle/config.js +4 -124
- package/dist/shared/flap/portal-bundle-merkle/core-helpers.d.ts +32 -0
- package/dist/shared/flap/portal-bundle-merkle/core-helpers.js +83 -0
- package/dist/shared/flap/portal-bundle-merkle/core.d.ts +0 -4
- package/dist/shared/flap/portal-bundle-merkle/core.js +66 -156
- package/dist/shared/flap/portal-bundle-merkle/create-to-dex.js +81 -86
- package/dist/shared/flap/portal-bundle-merkle/curve-to-dex.js +100 -92
- package/dist/shared/flap/portal-bundle-merkle/index.d.ts +11 -7
- package/dist/shared/flap/portal-bundle-merkle/index.js +4 -7
- package/dist/shared/flap/portal-bundle-merkle/pancake-proxy.js +71 -68
- package/dist/shared/flap/portal-bundle-merkle/private.js +61 -114
- package/dist/shared/flap/portal-bundle-merkle/swap-buy-first-helpers.d.ts +125 -0
- package/dist/shared/flap/portal-bundle-merkle/swap-buy-first-helpers.js +113 -0
- package/dist/shared/flap/portal-bundle-merkle/swap-buy-first.d.ts +1 -64
- package/dist/shared/flap/portal-bundle-merkle/swap-buy-first.js +66 -247
- package/dist/shared/flap/portal-bundle-merkle/swap-helpers.d.ts +149 -0
- package/dist/shared/flap/portal-bundle-merkle/swap-helpers.js +259 -0
- package/dist/shared/flap/portal-bundle-merkle/swap.d.ts +2 -71
- package/dist/shared/flap/portal-bundle-merkle/swap.js +103 -410
- package/dist/shared/flap/portal-bundle-merkle/types.d.ts +73 -3
- package/dist/shared/flap/portal-bundle-merkle/utils-helpers.d.ts +100 -0
- package/dist/shared/flap/portal-bundle-merkle/utils-helpers.js +133 -0
- package/dist/shared/flap/portal-bundle-merkle/utils.d.ts +1 -80
- package/dist/shared/flap/portal-bundle-merkle/utils.js +145 -265
- package/dist/shared/flap/portal-bundle.js +54 -42
- package/dist/shared/flap/portal.js +32 -10
- package/dist/shared/flap/vanity.js +4 -7
- package/dist/shared/flap/vault.d.ts +1 -1
- package/dist/shared/flap/vault.js +54 -48
- package/dist/shared/flap 2/__tests__/curve.test.d.ts +1 -0
- package/dist/shared/flap 2/portal-bundle-merkle/types.js +1 -0
- package/dist/shared/foundation/dex/v3-path.d.ts +6 -0
- package/dist/shared/foundation/dex/v3-path.js +35 -0
- package/dist/shared/foundation/gas/bundle-gas.d.ts +39 -0
- package/dist/shared/foundation/gas/bundle-gas.js +93 -0
- package/dist/shared/foundation/gas/profit-hop.d.ts +20 -0
- package/dist/shared/foundation/gas/profit-hop.js +72 -0
- package/dist/shared/foundation/index.d.ts +13 -0
- package/dist/shared/foundation/index.js +12 -0
- package/dist/shared/foundation/nonce/nonce-manager.d.ts +17 -0
- package/dist/shared/foundation/nonce/nonce-manager.js +180 -0
- package/dist/shared/foundation/normalize-unknown.d.ts +9 -0
- package/dist/shared/foundation/normalize-unknown.js +29 -0
- package/dist/shared/foundation/sdk-logger.d.ts +13 -0
- package/dist/shared/foundation/sdk-logger.js +12 -0
- package/dist/shared/foundation/tx/build-request.d.ts +17 -0
- package/dist/shared/foundation/tx/build-request.js +25 -0
- package/dist/shared/foundation/tx/sign-batch.d.ts +5 -0
- package/dist/shared/foundation/tx/sign-batch.js +26 -0
- package/dist/shared/foundation/tx/wallet-sign-patch.d.ts +1 -0
- package/dist/shared/foundation/tx/wallet-sign-patch.js +18 -0
- package/dist/shared/foundation/types/airdrop-sweep.d.ts +79 -0
- package/dist/shared/foundation/types/airdrop-sweep.js +1 -0
- package/dist/shared/foundation/types/erc20.d.ts +65 -0
- package/dist/shared/foundation/types/erc20.js +1 -0
- package/dist/shared/foundation/types/holders-maker.d.ts +64 -0
- package/dist/shared/foundation/types/holders-maker.js +1 -0
- package/dist/shared/foundation/types/index.d.ts +7 -0
- package/dist/shared/foundation/types/index.js +1 -0
- package/dist/shared/foundation/types/lp-inspect.d.ts +102 -0
- package/dist/shared/foundation/types/lp-inspect.js +1 -0
- package/dist/shared/foundation/types/multicall.d.ts +5 -0
- package/dist/shared/foundation/types/multicall.js +1 -0
- package/dist/shared/foundation/types/private-sale.d.ts +35 -0
- package/dist/shared/foundation/types/private-sale.js +1 -0
- package/dist/shared/foundation/types/quote-helpers.d.ts +17 -0
- package/dist/shared/foundation/types/quote-helpers.js +1 -0
- package/dist/shared/four/tax-token.d.ts +1 -1
- package/dist/shared/four/tax-token.js +27 -7
- package/dist/shared/index.d.ts +4 -0
- package/dist/shared/index.js +4 -0
- package/dist/types/distribute.d.ts +72 -0
- package/dist/types/distribute.js +1 -0
- package/dist/types 2/errors.d.ts +27 -0
- package/dist/types 2/errors.js +34 -0
- package/dist/utils/airdrop-sweep-types.d.ts +1 -0
- package/dist/utils/airdrop-sweep-types.js +1 -0
- package/dist/utils/airdrop-sweep.d.ts +4 -76
- package/dist/utils/airdrop-sweep.js +38 -52
- package/dist/utils/bundle-helpers.d.ts +9 -243
- package/dist/utils/bundle-helpers.js +10 -584
- package/dist/utils/constants.d.ts +5 -61
- package/dist/utils/constants.js +5 -80
- package/dist/utils/contract-factory.d.ts +2 -4
- package/dist/utils/contract-factory.js +25 -18
- package/dist/utils/erc20-types.d.ts +1 -0
- package/dist/utils/erc20-types.js +1 -0
- package/dist/utils/erc20.d.ts +8 -90
- package/dist/utils/erc20.js +94 -153
- package/dist/utils/errors.d.ts +10 -22
- package/dist/utils/errors.js +61 -79
- package/dist/utils/holders-maker/addresses.d.ts +12 -0
- package/dist/utils/holders-maker/addresses.js +15 -0
- package/dist/utils/holders-maker/buy-tx.d.ts +44 -0
- package/dist/utils/holders-maker/buy-tx.js +278 -0
- package/dist/utils/holders-maker/constants.d.ts +6 -0
- package/dist/utils/holders-maker/constants.js +7 -0
- package/dist/utils/holders-maker/disperse.d.ts +18 -0
- package/dist/utils/holders-maker/disperse.js +90 -0
- package/dist/utils/holders-maker/routing.d.ts +4 -0
- package/dist/utils/holders-maker/routing.js +45 -0
- package/dist/utils/holders-maker/transfer-tx.d.ts +4 -0
- package/dist/utils/holders-maker/transfer-tx.js +67 -0
- package/dist/utils/holders-maker-helpers.d.ts +9 -0
- package/dist/utils/holders-maker-helpers.js +9 -0
- package/dist/utils/holders-maker-types.d.ts +1 -0
- package/dist/utils/holders-maker-types.js +1 -0
- package/dist/utils/holders-maker.d.ts +2 -138
- package/dist/utils/holders-maker.js +23 -651
- package/dist/utils/hop-chains.d.ts +35 -0
- package/dist/utils/hop-chains.js +215 -0
- package/dist/utils/lp-inspect-helpers.d.ts +9 -0
- package/dist/utils/lp-inspect-helpers.js +109 -0
- package/dist/utils/lp-inspect-types.d.ts +1 -0
- package/dist/utils/lp-inspect-types.js +1 -0
- package/dist/utils/lp-inspect.d.ts +2 -112
- package/dist/utils/lp-inspect.js +63 -195
- package/dist/utils/mpcExclusive.d.ts +2 -5
- package/dist/utils/mpcExclusive.js +4 -3
- package/dist/utils/private-sale-types.d.ts +1 -0
- package/dist/utils/private-sale-types.js +1 -0
- package/dist/utils/private-sale.d.ts +2 -58
- package/dist/utils/private-sale.js +2 -7
- package/dist/utils/provider-factory.d.ts +4 -0
- package/dist/utils/provider-factory.js +10 -0
- package/dist/utils/quote-helpers-types.d.ts +1 -0
- package/dist/utils/quote-helpers-types.js +1 -0
- package/dist/utils/quote-helpers.d.ts +4 -45
- package/dist/utils/quote-helpers.js +15 -65
- package/dist/utils/stealth-transfer.d.ts +2 -28
- package/dist/utils/stealth-transfer.js +30 -14
- package/dist/utils/swap-helpers.d.ts +0 -3
- package/dist/utils/swap-helpers.js +6 -9
- package/dist/utils/types/airdrop-sweep.d.ts +1 -0
- package/dist/utils/types/airdrop-sweep.js +1 -0
- package/dist/utils/types/contract-factory.d.ts +1 -0
- package/dist/utils/types/contract-factory.js +1 -0
- package/dist/utils/types/erc20.d.ts +1 -0
- package/dist/utils/types/erc20.js +1 -0
- package/dist/utils/types/errors.d.ts +1 -0
- package/dist/utils/types/errors.js +1 -0
- package/dist/utils/types/holders-maker.d.ts +1 -0
- package/dist/utils/types/holders-maker.js +1 -0
- package/dist/utils/types/hop-chains.d.ts +8 -0
- package/dist/utils/types/hop-chains.js +1 -0
- package/dist/utils/types/index.d.ts +13 -0
- package/dist/utils/types/index.js +1 -0
- package/dist/utils/types/lp-inspect.d.ts +1 -0
- package/dist/utils/types/lp-inspect.js +1 -0
- package/dist/utils/types/mpc-exclusive.d.ts +5 -0
- package/dist/utils/types/mpc-exclusive.js +1 -0
- package/dist/utils/types/private-sale.d.ts +1 -0
- package/dist/utils/types/private-sale.js +1 -0
- package/dist/utils/types/quote-helpers.d.ts +1 -0
- package/dist/utils/types/quote-helpers.js +1 -0
- package/dist/utils/types/stealth-transfer.d.ts +44 -0
- package/dist/utils/types/stealth-transfer.js +1 -0
- package/dist/utils/types/wallet.d.ts +25 -0
- package/dist/utils/types/wallet.js +1 -0
- package/dist/utils/wallet.d.ts +2 -25
- package/dist/utils/wallet.js +9 -10
- package/package.json +55 -2
- package/src/abis/contracts/TaxToken.json +969 -0
- package/src/abis/contracts/TokenManager.json +836 -0
- package/src/abis/contracts/TokenManager2.json +136 -0
- package/src/abis/contracts/TokenManagerHelper3.json +993 -0
- /package/dist/{shared 2/flap/__tests__/curve.test.d.ts → bundle-core/__tests__/config-helpers.test.d.ts} +0 -0
- /package/dist/{shared 2/flap/portal-bundle-merkle/types.js → bundle-core/__tests__/facade-parity.test.d.ts} +0 -0
- /package/dist/{shared 2/abis → shared/abis 2}/TaxToken.json +0 -0
- /package/dist/{shared 2/abis → shared/abis 2}/TokenManager.json +0 -0
- /package/dist/{shared 2/abis → shared/abis 2}/TokenManager2.json +0 -0
- /package/dist/{shared 2/abis → shared/abis 2}/TokenManagerHelper3.json +0 -0
- /package/dist/{shared 2/abis → shared/abis 2}/common.d.ts +0 -0
- /package/dist/{shared 2/abis → shared/abis 2}/common.js +0 -0
- /package/dist/{shared 2/abis → shared/abis 2}/index.d.ts +0 -0
- /package/dist/{shared 2/abis → shared/abis 2}/index.js +0 -0
- /package/dist/{shared 2/clients → shared/clients 2}/blockrazor.d.ts +0 -0
- /package/dist/{shared 2/clients → shared/clients 2}/blockrazor.js +0 -0
- /package/dist/{shared 2/clients → shared/clients 2}/club48.d.ts +0 -0
- /package/dist/{shared 2/clients → shared/clients 2}/club48.js +0 -0
- /package/dist/{shared 2/clients → shared/clients 2}/emitservice.d.ts +0 -0
- /package/dist/{shared 2/clients → shared/clients 2}/emitservice.js +0 -0
- /package/dist/{shared 2/clients → shared/clients 2}/four.d.ts +0 -0
- /package/dist/{shared 2/clients → shared/clients 2}/four.js +0 -0
- /package/dist/{shared 2/clients → shared/clients 2}/merkle.d.ts +0 -0
- /package/dist/{shared 2/clients → shared/clients 2}/merkle.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/__tests__/curve.test.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/abi.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/abi.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/constants.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/constants.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/curve.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/curve.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/errors.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/errors.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/index.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/index.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/ipfs.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/ipfs.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/meta.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/meta.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/permit.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/permit.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/pinata.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/pinata.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/config.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/config.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/core.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/core.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/create-to-dex.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/create-to-dex.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/curve-to-dex.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/curve-to-dex.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/index.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/index.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/pancake-proxy.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/pancake-proxy.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/private.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/private.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/swap-buy-first.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/swap-buy-first.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/swap.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/swap.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/types.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/utils.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle-merkle/utils.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal-bundle.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/portal.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/vanity.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/vanity.js +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/vault.d.ts +0 -0
- /package/dist/{shared 2/flap → shared/flap 2}/vault.js +0 -0
- /package/dist/{shared 2/four → shared/four 2}/index.d.ts +0 -0
- /package/dist/{shared 2/four → shared/four 2}/index.js +0 -0
- /package/dist/{shared 2/four → shared/four 2}/tax-token.d.ts +0 -0
- /package/dist/{shared 2/four → shared/four 2}/tax-token.js +0 -0
- /package/dist/{shared 2/index.d.ts → shared/index 2.js} +0 -0
- /package/dist/{shared 2/index.js → shared/index.d 2.ts} +0 -0
|
@@ -1,262 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* 功能:钱包A卖出代币 → 钱包B买入相同数量 → 原子执行
|
|
2
|
+
* swap - 主函数
|
|
5
3
|
*/
|
|
6
4
|
import { ethers, Contract, Wallet } from 'ethers';
|
|
7
5
|
import { calculateSellAmount } from '../../../utils/swap-helpers.js';
|
|
8
|
-
import { NonceManager, getOptimizedGasPrice, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../../utils/bundle-helpers.js';
|
|
6
|
+
import { NonceManager, getOptimizedGasPrice, buildProfitHopTransactions, PROFIT_HOP_COUNT, } from '../../../utils/bundle-helpers.js';
|
|
9
7
|
import { FLAP_PORTAL_ADDRESSES } from '../constants.js';
|
|
10
|
-
import {
|
|
11
|
-
import { ERC20_ALLOWANCE_ABI,
|
|
12
|
-
import { getGasPriceConfig, getTxType, getProfitRecipient, getBribeAmount, BLOCKRAZOR_BUILDER_EOA, PORTAL_ABI } from './config.js';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const BRIBE_GAS_LIMIT = GAS_LIMITS.BRIBE;
|
|
19
|
-
/**
|
|
20
|
-
* 生成分发多跳路径
|
|
21
|
-
*/
|
|
22
|
-
function generateDisperseHopPaths(targetAddresses, hopCount, provider) {
|
|
23
|
-
if (hopCount <= 0) {
|
|
24
|
-
return targetAddresses.map(addr => ({
|
|
25
|
-
targetAddress: addr,
|
|
26
|
-
hopWallets: [],
|
|
27
|
-
hopWalletsInfo: []
|
|
28
|
-
}));
|
|
29
|
-
}
|
|
30
|
-
return targetAddresses.map(targetAddress => {
|
|
31
|
-
const hopWalletsInfo = generateWallets(hopCount);
|
|
32
|
-
const hopWallets = hopWalletsInfo.map(w => new Wallet(w.privateKey, provider));
|
|
33
|
-
return { targetAddress, hopWallets, hopWalletsInfo };
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* 构建原生代币多跳转账链
|
|
38
|
-
*/
|
|
39
|
-
async function buildNativeHopChain(payer, path, finalAmount, gasPrice, chainId, txType, payerNonce) {
|
|
40
|
-
const signedTxs = [];
|
|
41
|
-
const hopCount = path.hopWallets.length;
|
|
42
|
-
if (hopCount === 0) {
|
|
43
|
-
signedTxs.push(await payer.signTransaction({
|
|
44
|
-
to: path.targetAddress,
|
|
45
|
-
value: finalAmount,
|
|
46
|
-
nonce: payerNonce,
|
|
47
|
-
gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
|
|
48
|
-
gasPrice,
|
|
49
|
-
chainId,
|
|
50
|
-
type: txType
|
|
51
|
-
}));
|
|
52
|
-
return signedTxs;
|
|
53
|
-
}
|
|
54
|
-
const hopGasCost = NATIVE_TRANSFER_GAS_LIMIT * gasPrice;
|
|
55
|
-
// 计算每跳需要的金额
|
|
56
|
-
const amountsPerHop = [];
|
|
57
|
-
for (let i = 0; i < hopCount; i++) {
|
|
58
|
-
const remainingHops = hopCount - i;
|
|
59
|
-
amountsPerHop.push(finalAmount + hopGasCost * BigInt(remainingHops));
|
|
60
|
-
}
|
|
61
|
-
// payer → hop1
|
|
62
|
-
signedTxs.push(await payer.signTransaction({
|
|
63
|
-
to: path.hopWallets[0].address,
|
|
64
|
-
value: amountsPerHop[0],
|
|
65
|
-
nonce: payerNonce,
|
|
66
|
-
gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
|
|
67
|
-
gasPrice,
|
|
68
|
-
chainId,
|
|
69
|
-
type: txType
|
|
70
|
-
}));
|
|
71
|
-
// hop1 → hop2 → ... → target
|
|
72
|
-
for (let i = 0; i < hopCount; i++) {
|
|
73
|
-
const fromWallet = path.hopWallets[i];
|
|
74
|
-
const toAddress = i === hopCount - 1 ? path.targetAddress : path.hopWallets[i + 1].address;
|
|
75
|
-
const amount = i === hopCount - 1 ? finalAmount : amountsPerHop[i + 1];
|
|
76
|
-
signedTxs.push(await fromWallet.signTransaction({
|
|
77
|
-
to: toAddress,
|
|
78
|
-
value: amount,
|
|
79
|
-
nonce: 0,
|
|
80
|
-
gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
|
|
81
|
-
gasPrice,
|
|
82
|
-
chainId,
|
|
83
|
-
type: txType
|
|
84
|
-
}));
|
|
85
|
-
}
|
|
86
|
-
return signedTxs;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* 构建 ERC20 多跳转账链
|
|
90
|
-
*/
|
|
91
|
-
async function buildERC20HopChain(payer, path, erc20Address, erc20Amount, gasPrice, chainId, txType, payerNonce) {
|
|
92
|
-
const signedTxs = [];
|
|
93
|
-
const hopCount = path.hopWallets.length;
|
|
94
|
-
const erc20Interface = new ethers.Interface(ERC20_ABI);
|
|
95
|
-
if (hopCount === 0) {
|
|
96
|
-
const data = erc20Interface.encodeFunctionData('transfer', [path.targetAddress, erc20Amount]);
|
|
97
|
-
signedTxs.push(await payer.signTransaction({
|
|
98
|
-
to: erc20Address,
|
|
99
|
-
data,
|
|
100
|
-
value: 0n,
|
|
101
|
-
nonce: payerNonce,
|
|
102
|
-
gasLimit: ERC20_TRANSFER_GAS_LIMIT_HOP,
|
|
103
|
-
gasPrice,
|
|
104
|
-
chainId,
|
|
105
|
-
type: txType
|
|
106
|
-
}));
|
|
107
|
-
return signedTxs;
|
|
108
|
-
}
|
|
109
|
-
// payer → hop1
|
|
110
|
-
const firstData = erc20Interface.encodeFunctionData('transfer', [path.hopWallets[0].address, erc20Amount]);
|
|
111
|
-
signedTxs.push(await payer.signTransaction({
|
|
112
|
-
to: erc20Address,
|
|
113
|
-
data: firstData,
|
|
114
|
-
value: 0n,
|
|
115
|
-
nonce: payerNonce,
|
|
116
|
-
gasLimit: ERC20_TRANSFER_GAS_LIMIT_HOP,
|
|
117
|
-
gasPrice,
|
|
118
|
-
chainId,
|
|
119
|
-
type: txType
|
|
120
|
-
}));
|
|
121
|
-
// hop1 → hop2 → ... → target (nonce=1,nonce=0 用于 BNB 转发)
|
|
122
|
-
for (let i = 0; i < hopCount; i++) {
|
|
123
|
-
const fromWallet = path.hopWallets[i];
|
|
124
|
-
const toAddress = i === hopCount - 1 ? path.targetAddress : path.hopWallets[i + 1].address;
|
|
125
|
-
const data = erc20Interface.encodeFunctionData('transfer', [toAddress, erc20Amount]);
|
|
126
|
-
signedTxs.push(await fromWallet.signTransaction({
|
|
127
|
-
to: erc20Address,
|
|
128
|
-
data,
|
|
129
|
-
value: 0n,
|
|
130
|
-
nonce: 1, // nonce=0 已用于 BNB 转发
|
|
131
|
-
gasLimit: ERC20_TRANSFER_GAS_LIMIT_HOP,
|
|
132
|
-
gasPrice,
|
|
133
|
-
chainId,
|
|
134
|
-
type: txType
|
|
135
|
-
}));
|
|
136
|
-
}
|
|
137
|
-
return signedTxs;
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* 构建 BNB 多跳转账链(为 ERC20 中间钱包预留 gas)
|
|
141
|
-
*/
|
|
142
|
-
async function buildBNBHopChainForERC20(payer, path, finalGasAmount, gasPrice, chainId, txType, payerNonce) {
|
|
143
|
-
const signedTxs = [];
|
|
144
|
-
const hopCount = path.hopWallets.length;
|
|
145
|
-
if (hopCount === 0) {
|
|
146
|
-
return signedTxs;
|
|
147
|
-
}
|
|
148
|
-
const hopGasCost = NATIVE_TRANSFER_GAS_LIMIT * gasPrice;
|
|
149
|
-
const erc20GasCost = ERC20_TRANSFER_GAS_LIMIT_HOP * gasPrice;
|
|
150
|
-
const gasPerHop = hopGasCost + erc20GasCost * 2n;
|
|
151
|
-
const amountsPerHop = [];
|
|
152
|
-
for (let i = 0; i < hopCount; i++) {
|
|
153
|
-
const remainingHops = hopCount - i;
|
|
154
|
-
amountsPerHop.push(finalGasAmount + gasPerHop * BigInt(remainingHops));
|
|
155
|
-
}
|
|
156
|
-
// payer → hop1
|
|
157
|
-
signedTxs.push(await payer.signTransaction({
|
|
158
|
-
to: path.hopWallets[0].address,
|
|
159
|
-
value: amountsPerHop[0],
|
|
160
|
-
nonce: payerNonce,
|
|
161
|
-
gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
|
|
162
|
-
gasPrice,
|
|
163
|
-
chainId,
|
|
164
|
-
type: txType
|
|
165
|
-
}));
|
|
166
|
-
// hop1 → hop2 → ... → target (nonce=0)
|
|
167
|
-
for (let i = 0; i < hopCount; i++) {
|
|
168
|
-
const fromWallet = path.hopWallets[i];
|
|
169
|
-
const toAddress = i === hopCount - 1 ? path.targetAddress : path.hopWallets[i + 1].address;
|
|
170
|
-
const amount = i === hopCount - 1 ? finalGasAmount : amountsPerHop[i + 1];
|
|
171
|
-
signedTxs.push(await fromWallet.signTransaction({
|
|
172
|
-
to: toAddress,
|
|
173
|
-
value: amount,
|
|
174
|
-
nonce: 0,
|
|
175
|
-
gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
|
|
176
|
-
gasPrice,
|
|
177
|
-
chainId,
|
|
178
|
-
type: txType
|
|
179
|
-
}));
|
|
180
|
-
}
|
|
181
|
-
return signedTxs;
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* 获取 Gas Limit
|
|
185
|
-
*/
|
|
186
|
-
function getGasLimit(config, defaultGas = 500000) {
|
|
187
|
-
if (config.gasLimit !== undefined) {
|
|
188
|
-
return typeof config.gasLimit === 'bigint' ? config.gasLimit : BigInt(config.gasLimit);
|
|
189
|
-
}
|
|
190
|
-
const multiplier = config.gasLimitMultiplier ?? 1.0;
|
|
191
|
-
return BigInt(Math.ceil(defaultGas * multiplier));
|
|
192
|
-
}
|
|
193
|
-
// ✅ ABI 别名
|
|
194
|
-
const ROUTER_ABI = V2_ROUTER_QUOTE_ABI;
|
|
195
|
-
const ERC20_BALANCE_OF_ABI = ERC20_BALANCE_ABI;
|
|
196
|
-
const APPROVE_INTERFACE = new ethers.Interface(['function approve(address,uint256) returns (bool)']);
|
|
197
|
-
// ✅ 链常量
|
|
198
|
-
const BSC_PANCAKE_V2_ROUTER = ADDRESSES.BSC.PancakeV2Router;
|
|
199
|
-
const BSC_WBNB = ADDRESSES.BSC.WBNB;
|
|
200
|
-
const MONAD_PANCAKE_V2_ROUTER = '0xb1bc24c34e88f7d43d5923034e3a14b24daacff9';
|
|
201
|
-
const MONAD_WMON = ADDRESSES.MONAD.WMON;
|
|
202
|
-
/**
|
|
203
|
-
* 获取 ERC20 代币 → 原生代币的报价
|
|
204
|
-
* @param provider - Provider 实例
|
|
205
|
-
* @param tokenAddress - ERC20 代币地址
|
|
206
|
-
* @param tokenAmount - 代币数量(wei)
|
|
207
|
-
* @param chainId - 链 ID(56=BSC, 143=Monad)
|
|
208
|
-
* @returns 等值的原生代币数量(wei),失败返回 0n
|
|
209
|
-
*/
|
|
210
|
-
async function getTokenToNativeQuote(provider, tokenAddress, tokenAmount, chainId) {
|
|
211
|
-
if (tokenAmount <= 0n)
|
|
212
|
-
return 0n;
|
|
213
|
-
try {
|
|
214
|
-
if (chainId === CHAINS.BSC.chainId) {
|
|
215
|
-
// BSC: 使用 PancakeSwap V2 Router
|
|
216
|
-
const router = new Contract(BSC_PANCAKE_V2_ROUTER, ROUTER_ABI, provider);
|
|
217
|
-
const amounts = await router.getAmountsOut(tokenAmount, [tokenAddress, BSC_WBNB]);
|
|
218
|
-
return amounts[1];
|
|
219
|
-
}
|
|
220
|
-
if (chainId === CHAINS.MONAD.chainId) {
|
|
221
|
-
// ✅ Monad: 使用 PancakeSwap V2 Router
|
|
222
|
-
const router = new Contract(MONAD_PANCAKE_V2_ROUTER, ROUTER_ABI, provider);
|
|
223
|
-
const amounts = await router.getAmountsOut(tokenAmount, [tokenAddress, MONAD_WMON]);
|
|
224
|
-
return amounts[1];
|
|
225
|
-
}
|
|
226
|
-
// ✅ Base (8453) / XLayer (196) 等链暂不支持 V2 报价,返回 0
|
|
227
|
-
return 0n;
|
|
228
|
-
}
|
|
229
|
-
catch {
|
|
230
|
-
// 报价失败返回 0(可能是流动性不足或路径不存在)
|
|
231
|
-
return 0n;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* 获取链ID
|
|
236
|
-
*/
|
|
237
|
-
function getChainId(chain) {
|
|
238
|
-
switch (chain) {
|
|
239
|
-
case 'bsc': return 56;
|
|
240
|
-
case 'xlayer': return 196;
|
|
241
|
-
case 'base': return 8453;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* 获取原生代币名称
|
|
246
|
-
*/
|
|
247
|
-
function getNativeTokenName(chain) {
|
|
248
|
-
switch (chain) {
|
|
249
|
-
case 'bsc': return 'BNB';
|
|
250
|
-
case 'xlayer': return 'OKB';
|
|
251
|
-
case 'base': return 'ETH';
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Flap内盘捆绑换手
|
|
256
|
-
* ✅ 支持 quoteToken:传入 USDT 等地址时,卖出得到该代币,买入使用该代币
|
|
257
|
-
*/
|
|
8
|
+
import { ZERO_ADDRESS } from '../../../shared/constants/index.js';
|
|
9
|
+
import { ERC20_ALLOWANCE_ABI, ERC20_ABI } from '../../abis/common.js';
|
|
10
|
+
import { getGasPriceConfig, getTxType, getProfitRecipient, getBribeAmount, BLOCKRAZOR_BUILDER_EOA, PORTAL_ABI, } from './config.js';
|
|
11
|
+
import { getProfitRateBps as getSharedProfitRateBps } from '../../constants/index.js';
|
|
12
|
+
import { buildTransactionRequest } from '../../foundation/tx/build-request.js';
|
|
13
|
+
import { createSignProvider } from '../../../bundle-core/sign-context-helpers.js';
|
|
14
|
+
import { GAS_LIMITS } from '../../constants/index.js';
|
|
15
|
+
import { APPROVE_INTERFACE, BRIBE_GAS_LIMIT, ERC20_BALANCE_OF_ABI, NATIVE_TRANSFER_GAS_LIMIT, buildBNBHopChainForERC20, buildERC20HopChain, buildNativeHopChain, generateDisperseHopPaths, getChainId, getGasLimit, getNativeTokenName, getTokenToNativeQuote, } from './swap-helpers.js';
|
|
258
16
|
export async function flapBundleSwapMerkle(params) {
|
|
259
|
-
const { chain, sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, config, quoteToken, quoteTokenDecimals, startNonces // ✅ 可选:前端预获取的 nonces
|
|
17
|
+
const { chain, sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, config, quoteToken, quoteTokenDecimals, startNonces, // ✅ 可选:前端预获取的 nonces
|
|
260
18
|
} = params;
|
|
261
19
|
const chainContext = createChainContext(chain, config);
|
|
262
20
|
const seller = new Wallet(sellerPrivateKey, chainContext.provider);
|
|
@@ -270,7 +28,7 @@ export async function flapBundleSwapMerkle(params) {
|
|
|
270
28
|
// ✅ 优化:第一批并行 - calculateSellAmount、gasPrice
|
|
271
29
|
const [sellAmountResult, gasPrice] = await Promise.all([
|
|
272
30
|
calculateSellAmount(chainContext.provider, tokenAddress, seller.address, sellAmount, sellPercentage),
|
|
273
|
-
getOptimizedGasPrice(chainContext.provider, getGasPriceConfig(config))
|
|
31
|
+
getOptimizedGasPrice(chainContext.provider, getGasPriceConfig(config)),
|
|
274
32
|
]);
|
|
275
33
|
const { amount: sellAmountWei, decimals } = sellAmountResult;
|
|
276
34
|
const priorityFee = gasPrice / 10n === 0n ? 1n : gasPrice / 10n;
|
|
@@ -285,7 +43,7 @@ export async function flapBundleSwapMerkle(params) {
|
|
|
285
43
|
decimals,
|
|
286
44
|
portalAddress: chainContext.portalAddress,
|
|
287
45
|
chainId: chainContext.chainId,
|
|
288
|
-
config
|
|
46
|
+
config,
|
|
289
47
|
}),
|
|
290
48
|
quoteSellOutput({
|
|
291
49
|
portalAddress: chainContext.portalAddress,
|
|
@@ -293,8 +51,8 @@ export async function flapBundleSwapMerkle(params) {
|
|
|
293
51
|
sellAmountWei,
|
|
294
52
|
provider: chainContext.provider,
|
|
295
53
|
skipQuoteOnError: config.skipQuoteOnError,
|
|
296
|
-
outputToken // ✅ 传递输出代币
|
|
297
|
-
})
|
|
54
|
+
outputToken, // ✅ 传递输出代币
|
|
55
|
+
}),
|
|
298
56
|
]);
|
|
299
57
|
// ✅ 优化:第三批并行 - buyerNeed、validateBalances
|
|
300
58
|
const buyerNeed = await calculateBuyerNeed({
|
|
@@ -305,7 +63,7 @@ export async function flapBundleSwapMerkle(params) {
|
|
|
305
63
|
useNativeToken,
|
|
306
64
|
quoteToken,
|
|
307
65
|
quoteTokenDecimals,
|
|
308
|
-
provider: chainContext.provider
|
|
66
|
+
provider: chainContext.provider,
|
|
309
67
|
});
|
|
310
68
|
// ✅ 计算利润(基于卖出报价,根据 userType 动态调整)
|
|
311
69
|
const tokenProfitAmount = calculateProfitAmount(quote.quotedNative, config.userType);
|
|
@@ -327,16 +85,15 @@ export async function flapBundleSwapMerkle(params) {
|
|
|
327
85
|
outputToken, // ✅ 使用动态输出代币
|
|
328
86
|
inputAmount: sellAmountWei,
|
|
329
87
|
minOutputAmount: 0,
|
|
330
|
-
permitData: '0x'
|
|
88
|
+
permitData: '0x',
|
|
331
89
|
}),
|
|
332
90
|
portalBuyer.swapExactInput.populateTransaction({
|
|
333
91
|
inputToken: outputToken, // ✅ 使用动态输入代币
|
|
334
92
|
outputToken: tokenAddress,
|
|
335
93
|
inputAmount: buyerNeed.maxBuyerValue,
|
|
336
94
|
minOutputAmount: 0,
|
|
337
|
-
permitData: '0x'
|
|
338
|
-
}, useNativeToken ? { value: buyerNeed.maxBuyerValue } : {}
|
|
339
|
-
),
|
|
95
|
+
permitData: '0x',
|
|
96
|
+
}, useNativeToken ? { value: buyerNeed.maxBuyerValue } : {}),
|
|
340
97
|
// ✅ 如果前端传入了 startNonces,直接使用(性能优化)
|
|
341
98
|
startNonces && startNonces.length >= 2
|
|
342
99
|
? buildNoncePlan(startNonces, !!approvalTx, nativeProfitAmount > 0n, needBribeTx)
|
|
@@ -346,18 +103,16 @@ export async function flapBundleSwapMerkle(params) {
|
|
|
346
103
|
approvalExists: !!approvalTx,
|
|
347
104
|
extractProfit: nativeProfitAmount > 0n,
|
|
348
105
|
needBribeTx,
|
|
349
|
-
nonceManager
|
|
106
|
+
nonceManager,
|
|
350
107
|
}),
|
|
351
108
|
validateBalances({
|
|
352
|
-
buyerNeed,
|
|
353
109
|
buyerAddress: buyer.address,
|
|
354
110
|
portalGasCost: finalGasLimit * gasPrice,
|
|
355
111
|
provider: chainContext.provider,
|
|
356
112
|
chainContext,
|
|
357
113
|
seller,
|
|
358
|
-
useNativeToken,
|
|
359
|
-
|
|
360
|
-
})
|
|
114
|
+
useNativeToken,
|
|
115
|
+
}),
|
|
361
116
|
]);
|
|
362
117
|
// 构建交易请求
|
|
363
118
|
// ✅ 卖出交易 value 必须为 0,不能发送原生代币
|
|
@@ -369,7 +124,7 @@ export async function flapBundleSwapMerkle(params) {
|
|
|
369
124
|
priorityFee,
|
|
370
125
|
chainId: chainContext.chainId,
|
|
371
126
|
txType,
|
|
372
|
-
value: 0n // ✅ 卖出交易不发送原生代币
|
|
127
|
+
value: 0n, // ✅ 卖出交易不发送原生代币
|
|
373
128
|
});
|
|
374
129
|
const buyTx = buildTransactionRequest(buyUnsigned, {
|
|
375
130
|
from: buyer.address,
|
|
@@ -379,7 +134,7 @@ export async function flapBundleSwapMerkle(params) {
|
|
|
379
134
|
priorityFee,
|
|
380
135
|
chainId: chainContext.chainId,
|
|
381
136
|
txType,
|
|
382
|
-
value: useNativeToken ? buyerNeed.maxBuyerValue : 0n // ✅ ERC20 购买时 value=0
|
|
137
|
+
value: useNativeToken ? buyerNeed.maxBuyerValue : 0n, // ✅ ERC20 购买时 value=0
|
|
383
138
|
});
|
|
384
139
|
// ✅ 贿赂交易放在首位
|
|
385
140
|
let bribeTx = null;
|
|
@@ -391,14 +146,11 @@ export async function flapBundleSwapMerkle(params) {
|
|
|
391
146
|
gasPrice,
|
|
392
147
|
gasLimit: BRIBE_GAS_LIMIT,
|
|
393
148
|
chainId: chainContext.chainId,
|
|
394
|
-
type: txType
|
|
149
|
+
type: txType,
|
|
395
150
|
});
|
|
396
151
|
}
|
|
397
152
|
// ✅ 并行签名卖出和买入交易
|
|
398
|
-
const [signedSell, signedBuy] = await Promise.all([
|
|
399
|
-
seller.signTransaction(sellTx),
|
|
400
|
-
buyer.signTransaction(buyTx)
|
|
401
|
-
]);
|
|
153
|
+
const [signedSell, signedBuy] = await Promise.all([seller.signTransaction(sellTx), buyer.signTransaction(buyTx)]);
|
|
402
154
|
nonceManager.clearTemp();
|
|
403
155
|
// ✅ 组装顺序:贿赂 → 授权 → 卖出 → 买入
|
|
404
156
|
const allTransactions = [];
|
|
@@ -415,7 +167,7 @@ export async function flapBundleSwapMerkle(params) {
|
|
|
415
167
|
profitNonce: noncePlan.profitNonce,
|
|
416
168
|
gasPrice,
|
|
417
169
|
chainId: chainContext.chainId,
|
|
418
|
-
txType
|
|
170
|
+
txType,
|
|
419
171
|
});
|
|
420
172
|
if (profitResult)
|
|
421
173
|
allTransactions.push(...profitResult.signedTransactions);
|
|
@@ -430,8 +182,8 @@ export async function flapBundleSwapMerkle(params) {
|
|
|
430
182
|
? ethers.formatEther(buyerNeed.maxBuyerValue)
|
|
431
183
|
: ethers.formatUnits(buyerNeed.maxBuyerValue, quoteTokenDecimals ?? 18),
|
|
432
184
|
hasApproval: !!approvalTx,
|
|
433
|
-
profitAmount: nativeProfitAmount > 0n ? ethers.formatEther(nativeProfitAmount) : undefined // ✅ 显示原生代币利润
|
|
434
|
-
}
|
|
185
|
+
profitAmount: nativeProfitAmount > 0n ? ethers.formatEther(nativeProfitAmount) : undefined, // ✅ 显示原生代币利润
|
|
186
|
+
},
|
|
435
187
|
};
|
|
436
188
|
}
|
|
437
189
|
// ==================== 工具函数 ====================
|
|
@@ -451,15 +203,12 @@ function createChainContext(chain, config) {
|
|
|
451
203
|
provider = cached.provider;
|
|
452
204
|
}
|
|
453
205
|
else {
|
|
454
|
-
provider =
|
|
455
|
-
chainId,
|
|
456
|
-
name: chain.toUpperCase()
|
|
457
|
-
});
|
|
206
|
+
provider = createSignProvider(config.rpcUrl, chainId, chain.toUpperCase());
|
|
458
207
|
providerCache.set(cacheKey, { provider, expireAt: now + PROVIDER_CACHE_TTL_MS });
|
|
459
208
|
}
|
|
460
209
|
return { chainId, nativeToken, portalAddress, provider };
|
|
461
210
|
}
|
|
462
|
-
async function buildApprovalTransaction({ tokenAddress, seller, provider, decimals, portalAddress, chainId, config }) {
|
|
211
|
+
async function buildApprovalTransaction({ tokenAddress, seller, provider, decimals, portalAddress, chainId, config, }) {
|
|
463
212
|
const erc20 = new Contract(tokenAddress, ERC20_ALLOWANCE_ABI, provider);
|
|
464
213
|
const currentAllowance = await erc20.allowance(seller.address, portalAddress);
|
|
465
214
|
const threshold = ethers.parseUnits('1000000000', decimals);
|
|
@@ -478,17 +227,17 @@ async function buildApprovalTransaction({ tokenAddress, seller, provider, decima
|
|
|
478
227
|
gasLimit: 80000n,
|
|
479
228
|
gasPrice,
|
|
480
229
|
chainId,
|
|
481
|
-
type: txType
|
|
230
|
+
type: txType,
|
|
482
231
|
});
|
|
483
232
|
}
|
|
484
|
-
async function quoteSellOutput({ portalAddress, tokenAddress, sellAmountWei, provider, skipQuoteOnError, outputToken = ZERO_ADDRESS // ✅ 默认使用原生代币
|
|
233
|
+
async function quoteSellOutput({ portalAddress, tokenAddress, sellAmountWei, provider, skipQuoteOnError, outputToken = ZERO_ADDRESS, // ✅ 默认使用原生代币
|
|
485
234
|
}) {
|
|
486
235
|
const portal = new Contract(portalAddress, PORTAL_ABI, provider);
|
|
487
236
|
try {
|
|
488
237
|
const quotedNative = await portal.quoteExactInput.staticCall({
|
|
489
238
|
inputToken: tokenAddress,
|
|
490
239
|
outputToken, // ✅ 使用动态输出代币
|
|
491
|
-
inputAmount: sellAmountWei
|
|
240
|
+
inputAmount: sellAmountWei,
|
|
492
241
|
});
|
|
493
242
|
// ✅ 已移除滑点保护:minOutNative 固定为 0
|
|
494
243
|
return { quotedNative, minOutNative: 0n };
|
|
@@ -501,7 +250,7 @@ async function quoteSellOutput({ portalAddress, tokenAddress, sellAmountWei, pro
|
|
|
501
250
|
}
|
|
502
251
|
}
|
|
503
252
|
// ✅ ERC20_BALANCE_OF_ABI 已在文件开头定义
|
|
504
|
-
async function calculateBuyerNeed({ buyer, quotedNative, reserveGasEth, nativeToken, useNativeToken = true, quoteToken, quoteTokenDecimals = 18, provider }) {
|
|
253
|
+
async function calculateBuyerNeed({ buyer, quotedNative, reserveGasEth, nativeToken, useNativeToken = true, quoteToken, quoteTokenDecimals = 18, provider, }) {
|
|
505
254
|
const reserveGas = ethers.parseEther((reserveGasEth || 0.0005).toString());
|
|
506
255
|
// ✅ 根据是否使用原生代币获取不同的余额
|
|
507
256
|
let buyerBalance;
|
|
@@ -516,9 +265,7 @@ async function calculateBuyerNeed({ buyer, quotedNative, reserveGasEth, nativeTo
|
|
|
516
265
|
// ✅ 已移除滑点保护:直接使用报价金额
|
|
517
266
|
const estimatedBuyerNeed = quotedNative;
|
|
518
267
|
// ✅ 原生代币需要预留 Gas,ERC20 不需要
|
|
519
|
-
const buyerNeedTotal = useNativeToken
|
|
520
|
-
? estimatedBuyerNeed + reserveGas
|
|
521
|
-
: estimatedBuyerNeed;
|
|
268
|
+
const buyerNeedTotal = useNativeToken ? estimatedBuyerNeed + reserveGas : estimatedBuyerNeed;
|
|
522
269
|
if (buyerBalance < buyerNeedTotal) {
|
|
523
270
|
if (useNativeToken) {
|
|
524
271
|
throw new Error(`买方余额不足:\n` +
|
|
@@ -531,12 +278,10 @@ async function calculateBuyerNeed({ buyer, quotedNative, reserveGasEth, nativeTo
|
|
|
531
278
|
` - 实际: ${ethers.formatUnits(buyerBalance, quoteTokenDecimals)}`);
|
|
532
279
|
}
|
|
533
280
|
}
|
|
534
|
-
const maxBuyerValue = estimatedBuyerNeed > 0n
|
|
535
|
-
? estimatedBuyerNeed
|
|
536
|
-
: (useNativeToken ? buyerBalance - reserveGas : buyerBalance);
|
|
281
|
+
const maxBuyerValue = estimatedBuyerNeed > 0n ? estimatedBuyerNeed : useNativeToken ? buyerBalance - reserveGas : buyerBalance;
|
|
537
282
|
return { reserveGas, buyerBalance, buyerNeedTotal, maxBuyerValue };
|
|
538
283
|
}
|
|
539
|
-
async function validateBalances({
|
|
284
|
+
async function validateBalances({ buyerAddress, portalGasCost, provider, chainContext, seller, useNativeToken, }) {
|
|
540
285
|
const sellerBalance = await provider.getBalance(seller.address);
|
|
541
286
|
// ✅ 修复:买方余额已在 calculateBuyerNeed 中检查过
|
|
542
287
|
// 这里只需要检查:
|
|
@@ -578,14 +323,14 @@ function buildNoncePlan(startNonces, approvalExists, extractProfit, needBribeTx)
|
|
|
578
323
|
* ✅ 优化:使用批量 nonce 获取(JSON-RPC 批量请求)
|
|
579
324
|
* 交易顺序:贿赂 → 授权 → 卖出 → 买入 → 利润
|
|
580
325
|
*/
|
|
581
|
-
async function planNonces({ seller, buyer, approvalExists, extractProfit, needBribeTx, nonceManager }) {
|
|
326
|
+
async function planNonces({ seller, buyer, approvalExists, extractProfit, needBribeTx, nonceManager, }) {
|
|
582
327
|
if (needBribeTx || approvalExists || extractProfit) {
|
|
583
328
|
// 卖方需要多个 nonce:贿赂(可选) + 授权(可选) + 卖出 + 利润(可选)
|
|
584
329
|
const sellerTxCount = countTruthy([needBribeTx, approvalExists, true, extractProfit]);
|
|
585
330
|
// ✅ 优化:并行获取 seller 和 buyer 的 nonce
|
|
586
331
|
const [sellerNonces, buyerNonces] = await Promise.all([
|
|
587
332
|
nonceManager.getNextNonceBatch(seller, sellerTxCount),
|
|
588
|
-
nonceManager.getNextNoncesForWallets([buyer])
|
|
333
|
+
nonceManager.getNextNoncesForWallets([buyer]),
|
|
589
334
|
]);
|
|
590
335
|
let idx = 0;
|
|
591
336
|
const bribeNonce = needBribeTx ? sellerNonces[idx++] : undefined;
|
|
@@ -600,31 +345,10 @@ async function planNonces({ seller, buyer, approvalExists, extractProfit, needBr
|
|
|
600
345
|
const nonces = await nonceManager.getNextNoncesForWallets([seller, buyer]);
|
|
601
346
|
return { sellerNonce: nonces[0], buyerNonce: nonces[1] };
|
|
602
347
|
}
|
|
603
|
-
function buildTransactionRequest(unsigned, { from, nonce, gasLimit, gasPrice, priorityFee, chainId, txType, value }) {
|
|
604
|
-
const tx = {
|
|
605
|
-
...unsigned,
|
|
606
|
-
from,
|
|
607
|
-
nonce,
|
|
608
|
-
gasLimit,
|
|
609
|
-
chainId,
|
|
610
|
-
type: txType
|
|
611
|
-
};
|
|
612
|
-
if (value !== undefined) {
|
|
613
|
-
tx.value = value;
|
|
614
|
-
}
|
|
615
|
-
if (txType === 2) {
|
|
616
|
-
tx.maxFeePerGas = gasPrice;
|
|
617
|
-
tx.maxPriorityFeePerGas = priorityFee;
|
|
618
|
-
}
|
|
619
|
-
else {
|
|
620
|
-
tx.gasPrice = gasPrice;
|
|
621
|
-
}
|
|
622
|
-
return tx;
|
|
623
|
-
}
|
|
624
348
|
/**
|
|
625
349
|
* 构建利润多跳转账交易(强制 2 跳中转)
|
|
626
350
|
*/
|
|
627
|
-
async function buildProfitTransaction({ provider, seller, profitAmount, profitNonce, gasPrice, chainId, txType }) {
|
|
351
|
+
async function buildProfitTransaction({ provider, seller, profitAmount, profitNonce, gasPrice, chainId, txType, }) {
|
|
628
352
|
if (!profitNonce || profitAmount === 0n) {
|
|
629
353
|
return null;
|
|
630
354
|
}
|
|
@@ -637,11 +361,11 @@ async function buildProfitTransaction({ provider, seller, profitAmount, profitNo
|
|
|
637
361
|
gasPrice,
|
|
638
362
|
chainId,
|
|
639
363
|
txType,
|
|
640
|
-
startNonce: profitNonce
|
|
364
|
+
startNonce: profitNonce,
|
|
641
365
|
});
|
|
642
366
|
return {
|
|
643
367
|
signedTransactions: profitHopResult.signedTransactions,
|
|
644
|
-
hopWallets: profitHopResult.hopWallets
|
|
368
|
+
hopWallets: profitHopResult.hopWallets,
|
|
645
369
|
};
|
|
646
370
|
}
|
|
647
371
|
/**
|
|
@@ -649,12 +373,12 @@ async function buildProfitTransaction({ provider, seller, profitAmount, profitNo
|
|
|
649
373
|
*/
|
|
650
374
|
function getProfitRateBps(userType) {
|
|
651
375
|
if (userType === 'v0') {
|
|
652
|
-
return
|
|
376
|
+
return getSharedProfitRateBps('v0Single');
|
|
653
377
|
}
|
|
654
378
|
else if (userType === 'v1') {
|
|
655
|
-
return
|
|
379
|
+
return getSharedProfitRateBps('v1Single');
|
|
656
380
|
}
|
|
657
|
-
return
|
|
381
|
+
return getSharedProfitRateBps('v0Single');
|
|
658
382
|
}
|
|
659
383
|
function calculateProfitAmount(quotedNative, userType) {
|
|
660
384
|
if (quotedNative <= 0n) {
|
|
@@ -673,7 +397,7 @@ function countTruthy(values) {
|
|
|
673
397
|
* 限制:最多 24 个买方(服务器限制 25 笔交易,包含 1 笔利润交易)
|
|
674
398
|
*/
|
|
675
399
|
export async function flapBatchSwapMerkle(params) {
|
|
676
|
-
const { chain, sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, tokenAddress, config, quoteToken, quoteTokenDecimals = 18, startNonces // ✅ 可选:前端预获取的 nonces
|
|
400
|
+
const { chain, sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, tokenAddress, config, quoteToken, quoteTokenDecimals = 18, startNonces, // ✅ 可选:前端预获取的 nonces
|
|
677
401
|
} = params;
|
|
678
402
|
// ✅ 校验买方数量(最多 24 个)
|
|
679
403
|
const MAX_BUYERS = 24;
|
|
@@ -685,7 +409,7 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
685
409
|
}
|
|
686
410
|
const chainContext = createChainContext(chain, config);
|
|
687
411
|
const seller = new Wallet(sellerPrivateKey, chainContext.provider);
|
|
688
|
-
const buyers = buyerPrivateKeys.map(pk => new Wallet(pk, chainContext.provider));
|
|
412
|
+
const buyers = buyerPrivateKeys.map((pk) => new Wallet(pk, chainContext.provider));
|
|
689
413
|
const nonceManager = new NonceManager(chainContext.provider);
|
|
690
414
|
const finalGasLimit = getGasLimit(config);
|
|
691
415
|
const txType = getTxType(config);
|
|
@@ -695,7 +419,7 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
695
419
|
// ✅ 并行获取:卖出数量、gasPrice
|
|
696
420
|
const [sellAmountResult, gasPrice] = await Promise.all([
|
|
697
421
|
calculateSellAmount(chainContext.provider, tokenAddress, seller.address, sellAmount, sellPercentage),
|
|
698
|
-
getOptimizedGasPrice(chainContext.provider, getGasPriceConfig(config))
|
|
422
|
+
getOptimizedGasPrice(chainContext.provider, getGasPriceConfig(config)),
|
|
699
423
|
]);
|
|
700
424
|
const { amount: sellAmountWei, decimals } = sellAmountResult;
|
|
701
425
|
const priorityFee = gasPrice / 10n === 0n ? 1n : gasPrice / 10n;
|
|
@@ -710,7 +434,7 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
710
434
|
decimals,
|
|
711
435
|
portalAddress: chainContext.portalAddress,
|
|
712
436
|
chainId: chainContext.chainId,
|
|
713
|
-
config
|
|
437
|
+
config,
|
|
714
438
|
}),
|
|
715
439
|
quoteSellOutput({
|
|
716
440
|
portalAddress: chainContext.portalAddress,
|
|
@@ -718,15 +442,15 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
718
442
|
sellAmountWei,
|
|
719
443
|
provider: chainContext.provider,
|
|
720
444
|
skipQuoteOnError: config.skipQuoteOnError,
|
|
721
|
-
outputToken
|
|
722
|
-
})
|
|
445
|
+
outputToken,
|
|
446
|
+
}),
|
|
723
447
|
]);
|
|
724
448
|
// ✅ 计算每个买方的买入金额(按比例分配,已移除滑点保护)
|
|
725
449
|
const totalBuyAmount = quote.quotedNative;
|
|
726
450
|
let buyAmountsWei;
|
|
727
451
|
if (params.buyerRatios && params.buyerRatios.length === buyers.length) {
|
|
728
452
|
// 按比例分配
|
|
729
|
-
buyAmountsWei = params.buyerRatios.map((ratio
|
|
453
|
+
buyAmountsWei = params.buyerRatios.map((ratio) => {
|
|
730
454
|
const amount = (totalBuyAmount * BigInt(Math.round(ratio * 10000))) / 10000n;
|
|
731
455
|
return amount;
|
|
732
456
|
});
|
|
@@ -770,7 +494,7 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
770
494
|
outputToken,
|
|
771
495
|
inputAmount: sellAmountWei,
|
|
772
496
|
minOutputAmount: 0,
|
|
773
|
-
permitData: '0x'
|
|
497
|
+
permitData: '0x',
|
|
774
498
|
}),
|
|
775
499
|
// 所有买入交易
|
|
776
500
|
...buyers.map((buyer, i) => {
|
|
@@ -781,9 +505,9 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
781
505
|
outputToken: tokenAddress,
|
|
782
506
|
inputAmount: buyAmount,
|
|
783
507
|
minOutputAmount: 0,
|
|
784
|
-
permitData: '0x'
|
|
508
|
+
permitData: '0x',
|
|
785
509
|
}, useNativeToken ? { value: buyAmount } : {});
|
|
786
|
-
})
|
|
510
|
+
}),
|
|
787
511
|
]);
|
|
788
512
|
// ✅ 并行获取所有 nonce(如果前端传入了 startNonces,直接使用)
|
|
789
513
|
const allWallets = [seller, ...buyers];
|
|
@@ -795,7 +519,7 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
795
519
|
}
|
|
796
520
|
else {
|
|
797
521
|
sellNonce = await nonceManager.getNextNonce(seller);
|
|
798
|
-
buyerNonces = await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
|
|
522
|
+
buyerNonces = await Promise.all(buyers.map((buyer) => nonceManager.getNextNonce(buyer)));
|
|
799
523
|
}
|
|
800
524
|
// ✅ 贿赂交易和利润交易都由卖方发送(保持一致)
|
|
801
525
|
const bribeAmount = getBribeAmount(config);
|
|
@@ -810,7 +534,7 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
810
534
|
gasPrice,
|
|
811
535
|
gasLimit: BRIBE_GAS_LIMIT,
|
|
812
536
|
chainId: chainContext.chainId,
|
|
813
|
-
type: txType
|
|
537
|
+
type: txType,
|
|
814
538
|
});
|
|
815
539
|
bribeNonceOffset = 1; // 卖出交易的 nonce 需要 +1
|
|
816
540
|
}
|
|
@@ -826,7 +550,7 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
826
550
|
priorityFee,
|
|
827
551
|
chainId: chainContext.chainId,
|
|
828
552
|
txType,
|
|
829
|
-
value: 0n
|
|
553
|
+
value: 0n,
|
|
830
554
|
});
|
|
831
555
|
const [signedSell, ...signedBuys] = await Promise.all([
|
|
832
556
|
seller.signTransaction(sellTx),
|
|
@@ -839,10 +563,10 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
839
563
|
priorityFee,
|
|
840
564
|
chainId: chainContext.chainId,
|
|
841
565
|
txType,
|
|
842
|
-
value: useNativeToken ? buyAmountsWei[i] : 0n
|
|
566
|
+
value: useNativeToken ? buyAmountsWei[i] : 0n,
|
|
843
567
|
});
|
|
844
568
|
return buyer.signTransaction(buyTx);
|
|
845
|
-
})
|
|
569
|
+
}),
|
|
846
570
|
]);
|
|
847
571
|
// ✅ 按顺序组装交易数组:贿赂 → 授权 → 卖出 → 买入
|
|
848
572
|
const signedTransactions = [];
|
|
@@ -862,7 +586,7 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
862
586
|
profitNonce,
|
|
863
587
|
gasPrice,
|
|
864
588
|
chainId: chainContext.chainId,
|
|
865
|
-
txType
|
|
589
|
+
txType,
|
|
866
590
|
});
|
|
867
591
|
if (profitResult) {
|
|
868
592
|
signedTransactions.push(...profitResult.signedTransactions);
|
|
@@ -874,14 +598,12 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
874
598
|
profitHopWallets, // ✅ 导出利润多跳钱包
|
|
875
599
|
metadata: {
|
|
876
600
|
sellerAddress: seller.address,
|
|
877
|
-
buyerAddresses: buyers.map(b => b.address),
|
|
601
|
+
buyerAddresses: buyers.map((b) => b.address),
|
|
878
602
|
sellAmount: ethers.formatUnits(sellAmountWei, decimals),
|
|
879
|
-
buyAmounts: buyAmountsWei.map(amt => useNativeToken
|
|
880
|
-
? ethers.formatEther(amt)
|
|
881
|
-
: ethers.formatUnits(amt, quoteTokenDecimals)),
|
|
603
|
+
buyAmounts: buyAmountsWei.map((amt) => useNativeToken ? ethers.formatEther(amt) : ethers.formatUnits(amt, quoteTokenDecimals)),
|
|
882
604
|
hasApproval: !!approvalTx,
|
|
883
|
-
profitAmount: nativeProfitAmount > 0n ? ethers.formatEther(nativeProfitAmount) : undefined
|
|
884
|
-
}
|
|
605
|
+
profitAmount: nativeProfitAmount > 0n ? ethers.formatEther(nativeProfitAmount) : undefined,
|
|
606
|
+
},
|
|
885
607
|
};
|
|
886
608
|
}
|
|
887
609
|
/**
|
|
@@ -900,7 +622,7 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
900
622
|
*/
|
|
901
623
|
export async function flapQuickBatchSwapMerkle(params) {
|
|
902
624
|
const { chain, sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, config, quoteToken, quoteTokenDecimals = 18, disperseHopCount = 0, // ✅ 转账多跳数(默认0=直接转账)
|
|
903
|
-
startNonces // ✅ 可选:前端预获取的 nonces
|
|
625
|
+
startNonces, // ✅ 可选:前端预获取的 nonces
|
|
904
626
|
} = params;
|
|
905
627
|
// ✅ 判断是否使用原生代币
|
|
906
628
|
const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
|
|
@@ -918,7 +640,6 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
918
640
|
MAX_BUYERS = Math.floor(maxTxs / (2 * disperseHopCount + 3));
|
|
919
641
|
}
|
|
920
642
|
MAX_BUYERS = Math.max(1, MAX_BUYERS);
|
|
921
|
-
console.log(`[flapQuickBatchSwapMerkle] 多跳数: ${disperseHopCount}, 最大买方数: ${MAX_BUYERS}`);
|
|
922
643
|
if (buyerPrivateKeys.length === 0) {
|
|
923
644
|
throw new Error('至少需要一个买方钱包');
|
|
924
645
|
}
|
|
@@ -940,14 +661,14 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
940
661
|
const ERC20_TRANSFER_GAS = GAS_LIMITS.ERC20_TRANSFER;
|
|
941
662
|
const chainContext = createChainContext(chain, config);
|
|
942
663
|
const seller = new Wallet(sellerPrivateKey, chainContext.provider);
|
|
943
|
-
const buyers = buyerPrivateKeys.map(pk => new Wallet(pk, chainContext.provider));
|
|
664
|
+
const buyers = buyerPrivateKeys.map((pk) => new Wallet(pk, chainContext.provider));
|
|
944
665
|
const nonceManager = new NonceManager(chainContext.provider);
|
|
945
666
|
const finalGasLimit = getGasLimit(config);
|
|
946
667
|
const txType = getTxType(config);
|
|
947
668
|
// ✅ 并行获取:卖出数量、gasPrice
|
|
948
669
|
const [sellAmountResult, gasPrice] = await Promise.all([
|
|
949
670
|
calculateSellAmount(chainContext.provider, tokenAddress, seller.address, sellAmount, sellPercentage),
|
|
950
|
-
getOptimizedGasPrice(chainContext.provider, getGasPriceConfig(config))
|
|
671
|
+
getOptimizedGasPrice(chainContext.provider, getGasPriceConfig(config)),
|
|
951
672
|
]);
|
|
952
673
|
const { amount: sellAmountWei, decimals } = sellAmountResult;
|
|
953
674
|
const priorityFee = gasPrice / 10n === 0n ? 1n : gasPrice / 10n;
|
|
@@ -958,33 +679,22 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
958
679
|
sellAmountWei,
|
|
959
680
|
provider: chainContext.provider,
|
|
960
681
|
skipQuoteOnError: config.skipQuoteOnError,
|
|
961
|
-
outputToken
|
|
682
|
+
outputToken,
|
|
962
683
|
});
|
|
963
684
|
const estimatedOutput = quote.quotedNative;
|
|
964
|
-
const outputFormatted = useNativeToken
|
|
965
|
-
? ethers.formatEther(estimatedOutput)
|
|
966
|
-
: ethers.formatUnits(estimatedOutput, quoteTokenDecimals);
|
|
967
|
-
console.log(`[flapQuickBatchSwapMerkle] 模式: ${useNativeToken ? '原生代币' : 'ERC20'}`);
|
|
968
|
-
console.log(`[flapQuickBatchSwapMerkle] 卖出数量: ${ethers.formatUnits(sellAmountWei, decimals)}`);
|
|
969
|
-
console.log(`[flapQuickBatchSwapMerkle] 预估卖出所得: ${outputFormatted}`);
|
|
970
685
|
// ✅ 计算利润(根据 userType 动态调整)
|
|
971
|
-
|
|
686
|
+
const tokenProfitAmount = calculateProfitAmount(estimatedOutput, config.userType);
|
|
972
687
|
let nativeProfitAmount = tokenProfitAmount;
|
|
973
688
|
if (!useNativeToken && tokenProfitAmount > 0n) {
|
|
974
689
|
// ERC20 模式:将代币利润转换为等值原生代币
|
|
975
690
|
nativeProfitAmount = await getTokenToNativeQuote(chainContext.provider, quoteToken, tokenProfitAmount, chainContext.chainId);
|
|
976
|
-
console.log(`[flapQuickBatchSwapMerkle] ERC20→原生代币 报价: ${ethers.formatUnits(tokenProfitAmount, quoteTokenDecimals)} → ${ethers.formatEther(nativeProfitAmount)}`);
|
|
977
691
|
}
|
|
978
|
-
const distributableAmount = useNativeToken
|
|
979
|
-
? estimatedOutput - tokenProfitAmount
|
|
980
|
-
: estimatedOutput; // ERC20 模式利润从原生代币扣
|
|
692
|
+
const distributableAmount = useNativeToken ? estimatedOutput - tokenProfitAmount : estimatedOutput; // ERC20 模式利润从原生代币扣
|
|
981
693
|
// ✅ 计算每个买方分到的金额
|
|
982
694
|
let transferAmountsWei;
|
|
983
695
|
if (buyerAmounts && buyerAmounts.length === buyers.length) {
|
|
984
696
|
// 数量模式
|
|
985
|
-
transferAmountsWei = buyerAmounts.map(amt => useNativeToken
|
|
986
|
-
? ethers.parseEther(amt)
|
|
987
|
-
: ethers.parseUnits(amt, quoteTokenDecimals));
|
|
697
|
+
transferAmountsWei = buyerAmounts.map((amt) => useNativeToken ? ethers.parseEther(amt) : ethers.parseUnits(amt, quoteTokenDecimals));
|
|
988
698
|
const totalTransfer = transferAmountsWei.reduce((a, b) => a + b, 0n);
|
|
989
699
|
if (totalTransfer > distributableAmount) {
|
|
990
700
|
const formatted = useNativeToken
|
|
@@ -995,7 +705,7 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
995
705
|
}
|
|
996
706
|
else if (buyerRatios && buyerRatios.length === buyers.length) {
|
|
997
707
|
// 比例模式
|
|
998
|
-
transferAmountsWei = buyerRatios.map(ratio => {
|
|
708
|
+
transferAmountsWei = buyerRatios.map((ratio) => {
|
|
999
709
|
return (distributableAmount * BigInt(Math.round(ratio * 10000))) / 10000n;
|
|
1000
710
|
});
|
|
1001
711
|
}
|
|
@@ -1010,12 +720,14 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1010
720
|
let sellerRequired;
|
|
1011
721
|
if (useNativeToken) {
|
|
1012
722
|
// 原生代币模式:贿赂 + Gas(卖出 + 转账 + 利润)
|
|
1013
|
-
sellerGasCost =
|
|
723
|
+
sellerGasCost =
|
|
724
|
+
gasPrice * (BRIBE_GAS_LIMIT + finalGasLimit + BRIBE_GAS_LIMIT * BigInt(buyers.length) + BRIBE_GAS_LIMIT);
|
|
1014
725
|
sellerRequired = bribeAmount + sellerGasCost;
|
|
1015
726
|
}
|
|
1016
727
|
else {
|
|
1017
728
|
// ERC20 模式:贿赂 + Gas(卖出 + ERC20转账 + 利润)
|
|
1018
|
-
sellerGasCost =
|
|
729
|
+
sellerGasCost =
|
|
730
|
+
gasPrice * (BRIBE_GAS_LIMIT + finalGasLimit + ERC20_TRANSFER_GAS * BigInt(buyers.length) + BRIBE_GAS_LIMIT);
|
|
1019
731
|
sellerRequired = bribeAmount + sellerGasCost;
|
|
1020
732
|
}
|
|
1021
733
|
if (sellerBalance < sellerRequired) {
|
|
@@ -1023,9 +735,7 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1023
735
|
}
|
|
1024
736
|
// ==================== 规划 Nonce ====================
|
|
1025
737
|
// ✅ 如果前端传入了 startNonces,直接使用(性能优化)
|
|
1026
|
-
let sellerNonce = startNonces && startNonces.length > 0
|
|
1027
|
-
? startNonces[0]
|
|
1028
|
-
: await nonceManager.getNextNonce(seller);
|
|
738
|
+
let sellerNonce = startNonces && startNonces.length > 0 ? startNonces[0] : await nonceManager.getNextNonce(seller);
|
|
1029
739
|
// ==================== 1. 贿赂交易 ====================
|
|
1030
740
|
let bribeTx = null;
|
|
1031
741
|
if (bribeAmount > 0n) {
|
|
@@ -1036,9 +746,8 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1036
746
|
gasPrice,
|
|
1037
747
|
gasLimit: BRIBE_GAS_LIMIT,
|
|
1038
748
|
chainId: chainContext.chainId,
|
|
1039
|
-
type: txType
|
|
749
|
+
type: txType,
|
|
1040
750
|
});
|
|
1041
|
-
console.log(`[flapQuickBatchSwapMerkle] 贿赂交易已签名`);
|
|
1042
751
|
}
|
|
1043
752
|
// ==================== 2. 卖出交易 ====================
|
|
1044
753
|
const portalSeller = new Contract(chainContext.portalAddress, PORTAL_ABI, seller);
|
|
@@ -1047,7 +756,7 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1047
756
|
outputToken,
|
|
1048
757
|
inputAmount: sellAmountWei,
|
|
1049
758
|
minOutputAmount: 0,
|
|
1050
|
-
permitData: '0x'
|
|
759
|
+
permitData: '0x',
|
|
1051
760
|
});
|
|
1052
761
|
const sellTx = buildTransactionRequest(sellUnsigned, {
|
|
1053
762
|
from: seller.address,
|
|
@@ -1057,21 +766,20 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1057
766
|
priorityFee,
|
|
1058
767
|
chainId: chainContext.chainId,
|
|
1059
768
|
txType,
|
|
1060
|
-
value: 0n
|
|
769
|
+
value: 0n,
|
|
1061
770
|
});
|
|
1062
771
|
const signedSell = await seller.signTransaction(sellTx);
|
|
1063
|
-
console.log(`[flapQuickBatchSwapMerkle] 卖出交易已签名`);
|
|
1064
772
|
// ==================== 3. 转账交易(支持多跳)====================
|
|
1065
773
|
const reserveGas = ethers.parseEther((config.reserveGasETH || 0.0005).toString());
|
|
1066
774
|
const buyerGasCost = gasPrice * finalGasLimit;
|
|
1067
775
|
// ✅ 生成多跳路径
|
|
1068
|
-
const hopPaths = generateDisperseHopPaths(buyers.map(b => b.address), disperseHopCount, chainContext.provider);
|
|
776
|
+
const hopPaths = generateDisperseHopPaths(buyers.map((b) => b.address), disperseHopCount, chainContext.provider);
|
|
1069
777
|
// 收集所有中间钱包信息
|
|
1070
778
|
const allHopWallets = [];
|
|
1071
|
-
hopPaths.forEach(path => {
|
|
779
|
+
hopPaths.forEach((path) => {
|
|
1072
780
|
allHopWallets.push(...path.hopWalletsInfo);
|
|
1073
781
|
});
|
|
1074
|
-
let transferTxs
|
|
782
|
+
let transferTxs;
|
|
1075
783
|
if (disperseHopCount === 0) {
|
|
1076
784
|
// ✅ 无多跳:直接转账
|
|
1077
785
|
const transferNonces = buyers.map((_, i) => sellerNonce + i);
|
|
@@ -1086,17 +794,14 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1086
794
|
gasPrice,
|
|
1087
795
|
gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
|
|
1088
796
|
chainId: chainContext.chainId,
|
|
1089
|
-
type: txType
|
|
797
|
+
type: txType,
|
|
1090
798
|
});
|
|
1091
799
|
}));
|
|
1092
800
|
}
|
|
1093
801
|
else {
|
|
1094
802
|
const erc20Interface = new ethers.Interface(ERC20_ABI);
|
|
1095
803
|
transferTxs = await Promise.all(buyers.map((buyer, i) => {
|
|
1096
|
-
const transferData = erc20Interface.encodeFunctionData('transfer', [
|
|
1097
|
-
buyer.address,
|
|
1098
|
-
transferAmountsWei[i]
|
|
1099
|
-
]);
|
|
804
|
+
const transferData = erc20Interface.encodeFunctionData('transfer', [buyer.address, transferAmountsWei[i]]);
|
|
1100
805
|
return seller.signTransaction({
|
|
1101
806
|
to: quoteToken,
|
|
1102
807
|
data: transferData,
|
|
@@ -1105,7 +810,7 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1105
810
|
gasPrice,
|
|
1106
811
|
gasLimit: ERC20_TRANSFER_GAS,
|
|
1107
812
|
chainId: chainContext.chainId,
|
|
1108
|
-
type: txType
|
|
813
|
+
type: txType,
|
|
1109
814
|
});
|
|
1110
815
|
}));
|
|
1111
816
|
}
|
|
@@ -1144,12 +849,11 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1144
849
|
transferTxs = [...bnbTxs, ...erc20Txs];
|
|
1145
850
|
}
|
|
1146
851
|
}
|
|
1147
|
-
console.log(`[flapQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名 (多跳数=${disperseHopCount})`);
|
|
1148
852
|
// ==================== 4. 买入交易 ====================
|
|
1149
853
|
// ✅ 如果前端传入了 startNonces,使用 buyer 部分(从索引 1 开始)
|
|
1150
854
|
const buyerNonces = startNonces && startNonces.length > 1
|
|
1151
855
|
? startNonces.slice(1)
|
|
1152
|
-
: await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
|
|
856
|
+
: await Promise.all(buyers.map((buyer) => nonceManager.getNextNonce(buyer)));
|
|
1153
857
|
const signedBuys = await Promise.all(buyers.map(async (buyer, i) => {
|
|
1154
858
|
const buyAmount = transferAmountsWei[i];
|
|
1155
859
|
const portalBuyer = new Contract(chainContext.portalAddress, PORTAL_ABI, buyer);
|
|
@@ -1158,7 +862,7 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1158
862
|
outputToken: tokenAddress,
|
|
1159
863
|
inputAmount: buyAmount,
|
|
1160
864
|
minOutputAmount: 0,
|
|
1161
|
-
permitData: '0x'
|
|
865
|
+
permitData: '0x',
|
|
1162
866
|
}, useNativeToken ? { value: buyAmount } : {});
|
|
1163
867
|
const buyTx = buildTransactionRequest(buyUnsigned, {
|
|
1164
868
|
from: buyer.address,
|
|
@@ -1168,11 +872,10 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1168
872
|
priorityFee,
|
|
1169
873
|
chainId: chainContext.chainId,
|
|
1170
874
|
txType,
|
|
1171
|
-
value: useNativeToken ? buyAmount : 0n
|
|
875
|
+
value: useNativeToken ? buyAmount : 0n,
|
|
1172
876
|
});
|
|
1173
877
|
return buyer.signTransaction(buyTx);
|
|
1174
878
|
}));
|
|
1175
|
-
console.log(`[flapQuickBatchSwapMerkle] ${signedBuys.length} 笔买入交易已签名`);
|
|
1176
879
|
nonceManager.clearTemp();
|
|
1177
880
|
// ==================== 组装交易数组 ====================
|
|
1178
881
|
const signedTransactions = [];
|
|
@@ -1191,7 +894,7 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1191
894
|
profitNonce: sellerNonce++,
|
|
1192
895
|
gasPrice,
|
|
1193
896
|
chainId: chainContext.chainId,
|
|
1194
|
-
txType
|
|
897
|
+
txType,
|
|
1195
898
|
});
|
|
1196
899
|
if (profitResult) {
|
|
1197
900
|
signedTransactions.push(...profitResult.signedTransactions);
|
|
@@ -1199,29 +902,22 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1199
902
|
}
|
|
1200
903
|
// 多跳交易已签名
|
|
1201
904
|
}
|
|
1202
|
-
console.log(`[flapQuickBatchSwapMerkle] 交易组装完成: ${signedTransactions.length} 笔`);
|
|
1203
|
-
console.log(` - 贿赂: ${bribeTx ? 1 : 0}`);
|
|
1204
|
-
console.log(` - 卖出: 1`);
|
|
1205
|
-
console.log(` - 转账: ${transferTxs.length}`);
|
|
1206
|
-
console.log(` - 买入: ${signedBuys.length}`);
|
|
1207
905
|
return {
|
|
1208
906
|
signedTransactions,
|
|
1209
907
|
disperseHopWallets: allHopWallets.length > 0 ? allHopWallets : undefined, // ✅ 返回转账多跳钱包
|
|
1210
908
|
profitHopWallets, // ✅ 返回利润多跳钱包
|
|
1211
909
|
metadata: {
|
|
1212
910
|
sellerAddress: seller.address,
|
|
1213
|
-
buyerAddresses: buyers.map(b => b.address),
|
|
911
|
+
buyerAddresses: buyers.map((b) => b.address),
|
|
1214
912
|
sellAmount: ethers.formatUnits(sellAmountWei, decimals),
|
|
1215
913
|
estimatedOutput: useNativeToken
|
|
1216
914
|
? ethers.formatEther(estimatedOutput)
|
|
1217
915
|
: ethers.formatUnits(estimatedOutput, quoteTokenDecimals),
|
|
1218
|
-
transferAmounts: transferAmountsWei.map(amt => useNativeToken
|
|
1219
|
-
? ethers.formatEther(amt)
|
|
1220
|
-
: ethers.formatUnits(amt, quoteTokenDecimals)),
|
|
916
|
+
transferAmounts: transferAmountsWei.map((amt) => useNativeToken ? ethers.formatEther(amt) : ethers.formatUnits(amt, quoteTokenDecimals)),
|
|
1221
917
|
profitAmount: nativeProfitAmount > 0n ? ethers.formatEther(nativeProfitAmount) : undefined,
|
|
1222
918
|
useNativeToken,
|
|
1223
|
-
disperseHopCount: disperseHopCount > 0 ? disperseHopCount : undefined // ✅ 返回多跳数
|
|
1224
|
-
}
|
|
919
|
+
disperseHopCount: disperseHopCount > 0 ? disperseHopCount : undefined, // ✅ 返回多跳数
|
|
920
|
+
},
|
|
1225
921
|
};
|
|
1226
922
|
}
|
|
1227
923
|
/**
|
|
@@ -1232,7 +928,7 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1232
928
|
* - ✅ 正确处理 nonce:同一钱包在多轮中使用时 nonce 自动递增
|
|
1233
929
|
*/
|
|
1234
930
|
export async function flapCrossSwapMerkle(params) {
|
|
1235
|
-
const { chain, sellerPrivateKeys, sellAmounts, buyerPrivateKeys, tokenAddress, config, quoteToken, quoteTokenDecimals = 18, buyersPerSell, disperseHopCount = 0 } = params;
|
|
931
|
+
const { chain, sellerPrivateKeys, sellAmounts, buyerPrivateKeys, tokenAddress, config, quoteToken, quoteTokenDecimals = 18, buyersPerSell, disperseHopCount = 0, } = params;
|
|
1236
932
|
if (sellerPrivateKeys.length === 0) {
|
|
1237
933
|
throw new Error('至少需要一个卖方');
|
|
1238
934
|
}
|
|
@@ -1246,8 +942,8 @@ export async function flapCrossSwapMerkle(params) {
|
|
|
1246
942
|
const chainContext = createChainContext(chain, config);
|
|
1247
943
|
const nonceManager = new NonceManager(chainContext.provider);
|
|
1248
944
|
// ✅ 预先获取所有钱包的初始 nonce
|
|
1249
|
-
const allSellerWallets = sellerPrivateKeys.map(pk => new Wallet(pk, chainContext.provider));
|
|
1250
|
-
const allBuyerWallets = buyerPrivateKeys.map(pk => new Wallet(pk, chainContext.provider));
|
|
945
|
+
const allSellerWallets = sellerPrivateKeys.map((pk) => new Wallet(pk, chainContext.provider));
|
|
946
|
+
const allBuyerWallets = buyerPrivateKeys.map((pk) => new Wallet(pk, chainContext.provider));
|
|
1251
947
|
// 使用 Map 去重(同一私钥可能出现多次)
|
|
1252
948
|
const addressToNonce = new Map();
|
|
1253
949
|
// 获取所有卖方 nonce
|
|
@@ -1264,7 +960,6 @@ export async function flapCrossSwapMerkle(params) {
|
|
|
1264
960
|
addressToNonce.set(wallet.address, nonce);
|
|
1265
961
|
}
|
|
1266
962
|
}
|
|
1267
|
-
console.log(`[flapCrossSwapMerkle] 初始化完成: ${sellerPrivateKeys.length} 卖方, ${buyerPrivateKeys.length} 买方`);
|
|
1268
963
|
const allSigned = [];
|
|
1269
964
|
const allDisperse = [];
|
|
1270
965
|
const allProfit = [];
|
|
@@ -1288,7 +983,7 @@ export async function flapCrossSwapMerkle(params) {
|
|
|
1288
983
|
// ✅ 获取卖方当前 nonce
|
|
1289
984
|
const sellerNonce = addressToNonce.get(sellerWallet.address);
|
|
1290
985
|
// ✅ 获取并更新买方 nonces(每个买方本轮需要 1 个 nonce)
|
|
1291
|
-
const roundBuyerNonces = roundBuyerWallets.map(w => {
|
|
986
|
+
const roundBuyerNonces = roundBuyerWallets.map((w) => {
|
|
1292
987
|
const nonce = addressToNonce.get(w.address);
|
|
1293
988
|
addressToNonce.set(w.address, nonce + 1); // 每个买方用 1 个 nonce
|
|
1294
989
|
return nonce;
|
|
@@ -1330,11 +1025,10 @@ export async function flapCrossSwapMerkle(params) {
|
|
|
1330
1025
|
quoteToken,
|
|
1331
1026
|
quoteTokenDecimals,
|
|
1332
1027
|
disperseHopCount,
|
|
1333
|
-
startNonces // ✅ 传入预计算的 nonces
|
|
1028
|
+
startNonces, // ✅ 传入预计算的 nonces
|
|
1334
1029
|
});
|
|
1335
1030
|
// ✅ 更新卖方 nonce(使用精确计算的值)
|
|
1336
1031
|
addressToNonce.set(sellerWallet.address, sellerNonce + sellerNonceConsumed);
|
|
1337
|
-
console.log(`[flapCrossSwapMerkle] 轮次 ${i + 1}: 卖方=${sellerWallet.address.slice(0, 10)}..., 买方=${roundBuyerPks.length}, 交易=${res.signedTransactions.length}`);
|
|
1338
1032
|
// 累积签名与中间钱包
|
|
1339
1033
|
allSigned.push(...res.signedTransactions);
|
|
1340
1034
|
if (res.disperseHopWallets)
|
|
@@ -1345,15 +1039,14 @@ export async function flapCrossSwapMerkle(params) {
|
|
|
1345
1039
|
sellerAddress: res.metadata?.sellerAddress || '',
|
|
1346
1040
|
buyerAddresses: res.metadata?.buyerAddresses || roundBuyerPks.map(() => ''),
|
|
1347
1041
|
sellAmount,
|
|
1348
|
-
bundleHash: undefined
|
|
1042
|
+
bundleHash: undefined,
|
|
1349
1043
|
});
|
|
1350
1044
|
}
|
|
1351
1045
|
nonceManager.clearTemp();
|
|
1352
|
-
console.log(`[flapCrossSwapMerkle] 完成: ${rounds.length} 轮, ${allSigned.length} 笔交易`);
|
|
1353
1046
|
return {
|
|
1354
1047
|
signedTransactions: allSigned,
|
|
1355
1048
|
rounds,
|
|
1356
1049
|
disperseHopWallets: allDisperse.length > 0 ? allDisperse : undefined,
|
|
1357
|
-
profitHopWallets: allProfit.length > 0 ? allProfit : undefined
|
|
1050
|
+
profitHopWallets: allProfit.length > 0 ? allProfit : undefined,
|
|
1358
1051
|
};
|
|
1359
1052
|
}
|