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