wayfinder-paths 0.1.28__tar.gz → 0.1.30__tar.gz
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.
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/PKG-INFO +1 -1
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/pyproject.toml +1 -1
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/adapter.py +445 -14
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/client.py +7 -5
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/test_adapter.py +259 -19
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +4 -14
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/exchange.py +2 -2
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/local_signer.py +2 -33
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/multicall_adapter/adapter.py +2 -4
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/TokenClient.py +1 -1
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/__init__.py +23 -1
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/contracts.py +22 -0
- wayfinder_paths-0.1.30/wayfinder_paths/core/constants/hype_oft_abi.py +151 -0
- wayfinder_paths-0.1.30/wayfinder_paths/core/constants/hyperliquid.py +33 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/engine/manifest.py +1 -1
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/strategies/Strategy.py +1 -2
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/scripting.py +2 -2
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/discovery.py +3 -72
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/execute.py +8 -4
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/hyperliquid.py +1 -1
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/quotes.py +11 -133
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/wallets.py +4 -7
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/utils.py +0 -22
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/lifi.py +5 -2
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/moonwell.py +3 -1
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/util.py +4 -2
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/strategy.py +2 -4
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/boros_ops_mixin.py +57 -201
- wayfinder_paths-0.1.30/wayfinder_paths/strategies/boros_hype_strategy/constants.py +127 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/strategy.py +24 -63
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +2 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +2 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +4 -1
- wayfinder_paths-0.1.28/wayfinder_paths/core/constants/hyperliquid.py +0 -16
- wayfinder_paths-0.1.28/wayfinder_paths/core/types.py +0 -19
- wayfinder_paths-0.1.28/wayfinder_paths/strategies/boros_hype_strategy/constants.py +0 -271
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/LICENSE +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/README.md +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/balance_adapter/README.md +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/balance_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/balance_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/balance_adapter/manifest.yaml +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/balance_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/manifest.yaml +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/parsers.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/test_golden.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/types.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/utils.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/brap_adapter/README.md +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/brap_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/brap_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/brap_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/brap_adapter/manifest.yaml +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/brap_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperlend_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperlend_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperlend_adapter/manifest.yaml +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/executor.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/manifest.yaml +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/test_executor.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/util.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/utils.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/ledger_adapter/README.md +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/ledger_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/ledger_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/ledger_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/ledger_adapter/manifest.yaml +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/ledger_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/moonwell_adapter/README.md +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/moonwell_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/moonwell_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/moonwell_adapter/manifest.yaml +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/multicall_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/multicall_adapter/manifest.yaml +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/multicall_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pendle_adapter/README.md +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pendle_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pendle_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pendle_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pendle_adapter/manifest.yaml +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pendle_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pool_adapter/README.md +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pool_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pool_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pool_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pool_adapter/manifest.yaml +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pool_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/token_adapter/README.md +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/token_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/token_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/token_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/token_adapter/manifest.yaml +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/token_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/conftest.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/adapters/BaseAdapter.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/adapters/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/adapters/models.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/analytics/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/analytics/bootstrap.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/analytics/stats.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/analytics/test_analytics.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/BRAPClient.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/BalanceClient.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/ClientManager.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/HyperlendClient.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/LedgerClient.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/PoolClient.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/WayfinderClient.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/protocols.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/test_ledger_client.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/config.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/base.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/chains.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/erc20_abi.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/hyperlend_abi.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/moonwell_abi.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/tokens.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/strategies/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/strategies/base.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/strategies/descriptors.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/strategies/opa_loop.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/evm_helpers.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/test_transaction.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/tokens.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/transaction.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/wallets.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/web3.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/preview.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/server.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/state/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/state/profile_store.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/state/store.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/test_scripting.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/balances.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/run_script.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/strategies.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/tokens.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/enso.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/erc20.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/evm.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/hyper_evm.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/hyperlend.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/hyperliquid.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/prjx.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/run_strategy.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/README.md +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/constants.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/snapshot_mixin.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/types.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/hyperevm_ops_mixin.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/hyperliquid_ops_mixin.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/manifest.yaml +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/planner.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/risk_ops_mixin.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/snapshot_mixin.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/test_planner_golden.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/types.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/withdraw_mixin.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/README.md +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/stablecoin_yield_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/tests/__init__.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/tests/test_mcp_quote_swap.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/tests/test_test_coverage.py +0 -0
- {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/tests/test_utils.py +0 -0
{wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/adapter.py
RENAMED
|
@@ -5,15 +5,20 @@ import time
|
|
|
5
5
|
from collections.abc import Callable
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
|
-
from eth_abi import encode
|
|
8
|
+
from eth_abi import decode, encode
|
|
9
9
|
from eth_utils import function_signature_to_4byte_selector, to_checksum_address
|
|
10
10
|
from loguru import logger
|
|
11
11
|
|
|
12
12
|
from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
|
|
13
|
-
from wayfinder_paths.core.constants.
|
|
14
|
-
from wayfinder_paths.core.constants.contracts import
|
|
13
|
+
from wayfinder_paths.core.constants.chains import CHAIN_ID_HYPEREVM
|
|
14
|
+
from wayfinder_paths.core.constants.contracts import (
|
|
15
|
+
BOROS_MARKET_HUB,
|
|
16
|
+
BOROS_ROUTER,
|
|
17
|
+
HYPE_OFT_ADDRESS,
|
|
18
|
+
)
|
|
19
|
+
from wayfinder_paths.core.constants.hype_oft_abi import HYPE_OFT_ABI
|
|
15
20
|
from wayfinder_paths.core.utils.tokens import build_approve_transaction
|
|
16
|
-
from wayfinder_paths.core.utils.transaction import send_transaction
|
|
21
|
+
from wayfinder_paths.core.utils.transaction import encode_call, send_transaction
|
|
17
22
|
from wayfinder_paths.core.utils.web3 import web3_from_chain_id
|
|
18
23
|
|
|
19
24
|
from .client import BorosClient
|
|
@@ -115,6 +120,120 @@ class BorosAdapter(BaseAdapter):
|
|
|
115
120
|
}
|
|
116
121
|
]
|
|
117
122
|
|
|
123
|
+
@staticmethod
|
|
124
|
+
def _pad_address_bytes32(address: str) -> bytes:
|
|
125
|
+
checksum = to_checksum_address(address)
|
|
126
|
+
return bytes.fromhex(checksum[2:]).rjust(32, b"\x00")
|
|
127
|
+
|
|
128
|
+
async def get_cash_fee_data(self, *, token_id: int) -> tuple[bool, dict[str, Any]]:
|
|
129
|
+
"""Read MarketHub.getCashFeeData(tokenId) from chain.
|
|
130
|
+
|
|
131
|
+
This is useful for guarding Boros actions that require a minimum amount
|
|
132
|
+
of cross cash (e.g., MMInsufficientMinCash()).
|
|
133
|
+
"""
|
|
134
|
+
try:
|
|
135
|
+
selector = function_signature_to_4byte_selector("getCashFeeData(uint16)")
|
|
136
|
+
params = encode(["uint16"], [int(token_id)])
|
|
137
|
+
data = "0x" + selector.hex() + params.hex()
|
|
138
|
+
|
|
139
|
+
async with web3_from_chain_id(self.chain_id) as web3:
|
|
140
|
+
raw: bytes = await web3.eth.call(
|
|
141
|
+
{
|
|
142
|
+
"to": to_checksum_address(BOROS_MARKET_HUB),
|
|
143
|
+
"data": data,
|
|
144
|
+
}
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
if len(raw) % 32 != 0:
|
|
148
|
+
return False, {"error": f"Unexpected getCashFeeData() size: {len(raw)}"}
|
|
149
|
+
|
|
150
|
+
n_words = len(raw) // 32
|
|
151
|
+
values = decode(["uint256"] * n_words, raw)
|
|
152
|
+
if len(values) < 4:
|
|
153
|
+
return False, {
|
|
154
|
+
"error": f"Unexpected getCashFeeData() words: {len(values)}"
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
# Empirically (2026-02-01 on Arbitrum MarketHub), the return is 4 uint256s.
|
|
158
|
+
# We expose all 4, and provide float conversions for the commonly used ones.
|
|
159
|
+
scaling_factor_wei = int(values[0])
|
|
160
|
+
fee_rate_wei = int(values[1])
|
|
161
|
+
min_cash_cross_wei = int(values[2])
|
|
162
|
+
min_cash_isolated_wei = int(values[3])
|
|
163
|
+
|
|
164
|
+
return True, {
|
|
165
|
+
"token_id": int(token_id),
|
|
166
|
+
"scaling_factor_wei": scaling_factor_wei,
|
|
167
|
+
"fee_rate_wei": fee_rate_wei,
|
|
168
|
+
"min_cash_cross_wei": min_cash_cross_wei,
|
|
169
|
+
"min_cash_isolated_wei": min_cash_isolated_wei,
|
|
170
|
+
"fee_rate": fee_rate_wei / 1e18,
|
|
171
|
+
"min_cash_cross": min_cash_cross_wei / 1e18,
|
|
172
|
+
"min_cash_isolated": min_cash_isolated_wei / 1e18,
|
|
173
|
+
}
|
|
174
|
+
except Exception as exc: # noqa: BLE001
|
|
175
|
+
return False, {"error": str(exc)}
|
|
176
|
+
|
|
177
|
+
async def sweep_isolated_to_cross(
|
|
178
|
+
self,
|
|
179
|
+
*,
|
|
180
|
+
token_id: int,
|
|
181
|
+
market_id: int | None = None,
|
|
182
|
+
) -> tuple[bool, dict[str, Any]]:
|
|
183
|
+
"""Sweep isolated cash -> cross cash for a given token (optionally per-market).
|
|
184
|
+
|
|
185
|
+
Boros deposits can sometimes show up as isolated cash for the target market;
|
|
186
|
+
this helper moves that isolated cash back to cross margin using cash_transfer.
|
|
187
|
+
|
|
188
|
+
Notes:
|
|
189
|
+
- Uses `get_account_balances()` (collaterals endpoint) to find isolated cash.
|
|
190
|
+
- cash_transfer uses 1e18 internal cash units, not token native decimals.
|
|
191
|
+
- This does NOT touch isolated positions for other markets unless market_id is None.
|
|
192
|
+
"""
|
|
193
|
+
if self.simulation:
|
|
194
|
+
return True, {"status": "simulated"}
|
|
195
|
+
|
|
196
|
+
ok_bal, balances = await self.get_account_balances(token_id=int(token_id))
|
|
197
|
+
if not ok_bal or not isinstance(balances, dict):
|
|
198
|
+
return False, {"error": f"Failed to read Boros balances: {balances}"}
|
|
199
|
+
|
|
200
|
+
isolated_positions = balances.get("isolated_positions") or []
|
|
201
|
+
if not isinstance(isolated_positions, list):
|
|
202
|
+
isolated_positions = []
|
|
203
|
+
|
|
204
|
+
moved: list[dict[str, Any]] = []
|
|
205
|
+
for iso in isolated_positions:
|
|
206
|
+
try:
|
|
207
|
+
iso_market_id = int(iso.get("market_id"))
|
|
208
|
+
if market_id is not None and iso_market_id != int(market_id):
|
|
209
|
+
continue
|
|
210
|
+
balance_wei = int(iso.get("balance_wei") or 0)
|
|
211
|
+
if balance_wei <= 0:
|
|
212
|
+
continue
|
|
213
|
+
|
|
214
|
+
tx_ok, tx_res = await self.cash_transfer(
|
|
215
|
+
market_id=iso_market_id,
|
|
216
|
+
amount_wei=balance_wei,
|
|
217
|
+
is_deposit=False, # isolated -> cross
|
|
218
|
+
)
|
|
219
|
+
moved.append(
|
|
220
|
+
{
|
|
221
|
+
"market_id": iso_market_id,
|
|
222
|
+
"balance_wei": balance_wei,
|
|
223
|
+
"ok": tx_ok,
|
|
224
|
+
"tx": tx_res,
|
|
225
|
+
}
|
|
226
|
+
)
|
|
227
|
+
if not tx_ok:
|
|
228
|
+
return False, {
|
|
229
|
+
"error": f"Failed sweep isolated->cross for market {iso_market_id}",
|
|
230
|
+
"moved": moved,
|
|
231
|
+
}
|
|
232
|
+
except Exception as exc: # noqa: BLE001
|
|
233
|
+
return False, {"error": f"Failed sweep isolated->cross: {exc}"}
|
|
234
|
+
|
|
235
|
+
return True, {"status": "ok", "moved": moved}
|
|
236
|
+
|
|
118
237
|
@staticmethod
|
|
119
238
|
def _unwrap_tx_payload(payload: dict[str, Any]) -> dict[str, Any]:
|
|
120
239
|
"""Best-effort unwrap of API payloads that may nest the tx dict."""
|
|
@@ -195,7 +314,6 @@ class BorosAdapter(BaseAdapter):
|
|
|
195
314
|
self,
|
|
196
315
|
calldata: dict[str, Any],
|
|
197
316
|
*,
|
|
198
|
-
timeout: int = DEFAULT_TRANSACTION_TIMEOUT,
|
|
199
317
|
max_retries: int = 2,
|
|
200
318
|
) -> tuple[bool, dict[str, Any]]:
|
|
201
319
|
"""Broadcast calldata from Boros API with retry logic.
|
|
@@ -292,14 +410,6 @@ class BorosAdapter(BaseAdapter):
|
|
|
292
410
|
"attempts": max_retries + 1,
|
|
293
411
|
}
|
|
294
412
|
|
|
295
|
-
async def connect(self) -> bool:
|
|
296
|
-
try:
|
|
297
|
-
markets = await self.boros_client.list_markets(limit=1)
|
|
298
|
-
return len(markets) > 0
|
|
299
|
-
except Exception as exc:
|
|
300
|
-
logger.error(f"BorosAdapter connection failed: {exc}")
|
|
301
|
-
return False
|
|
302
|
-
|
|
303
413
|
# ------------------------------------------------------------------ #
|
|
304
414
|
# Tick Math Utilities #
|
|
305
415
|
# ------------------------------------------------------------------ #
|
|
@@ -1015,6 +1125,14 @@ class BorosAdapter(BaseAdapter):
|
|
|
1015
1125
|
token_id: int,
|
|
1016
1126
|
market_id: int,
|
|
1017
1127
|
) -> tuple[bool, dict[str, Any]]:
|
|
1128
|
+
"""Deposit collateral into Boros cross margin.
|
|
1129
|
+
|
|
1130
|
+
IMPORTANT: amount_wei is in the collateral token's native decimals.
|
|
1131
|
+
Example: USDT has 6 decimals, so 1 USDT = 1_000_000.
|
|
1132
|
+
|
|
1133
|
+
After deposit, Boros may credit the cash as isolated for market_id. This
|
|
1134
|
+
helper sweeps isolated -> cross for that market to match the method name.
|
|
1135
|
+
"""
|
|
1018
1136
|
if self.simulation:
|
|
1019
1137
|
logger.info(
|
|
1020
1138
|
f"[SIMULATION] deposit_to_cross_margin: {amount_wei} wei, "
|
|
@@ -1074,7 +1192,24 @@ class BorosAdapter(BaseAdapter):
|
|
|
1074
1192
|
"tx": tx_res,
|
|
1075
1193
|
}
|
|
1076
1194
|
|
|
1077
|
-
|
|
1195
|
+
sweep_ok, sweep_res = await self.sweep_isolated_to_cross(
|
|
1196
|
+
token_id=int(token_id),
|
|
1197
|
+
market_id=int(market_id),
|
|
1198
|
+
)
|
|
1199
|
+
if not sweep_ok:
|
|
1200
|
+
return False, {
|
|
1201
|
+
"error": f"Deposit succeeded but isolated->cross sweep failed: {sweep_res}",
|
|
1202
|
+
"approve": approve_res,
|
|
1203
|
+
"tx": tx_res,
|
|
1204
|
+
"sweep": sweep_res,
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
return True, {
|
|
1208
|
+
"status": "ok",
|
|
1209
|
+
"approve": approve_res,
|
|
1210
|
+
"tx": tx_res,
|
|
1211
|
+
"sweep": sweep_res,
|
|
1212
|
+
}
|
|
1078
1213
|
except Exception as e:
|
|
1079
1214
|
logger.error(f"Failed to deposit to cross margin: {e}")
|
|
1080
1215
|
return False, {"error": str(e)}
|
|
@@ -1174,6 +1309,302 @@ class BorosAdapter(BaseAdapter):
|
|
|
1174
1309
|
logger.error(f"Failed to cash transfer: {e}")
|
|
1175
1310
|
return False, {"error": str(e)}
|
|
1176
1311
|
|
|
1312
|
+
async def bridge_hype_oft_hyperevm_to_arbitrum(
|
|
1313
|
+
self,
|
|
1314
|
+
*,
|
|
1315
|
+
amount_wei: int,
|
|
1316
|
+
max_value_wei: int | None = None,
|
|
1317
|
+
to_address: str | None = None,
|
|
1318
|
+
from_address: str | None = None,
|
|
1319
|
+
dst_eid: int = 30110,
|
|
1320
|
+
min_amount_wei: int = 0,
|
|
1321
|
+
) -> tuple[bool, dict[str, Any]]:
|
|
1322
|
+
"""Bridge native HYPE from HyperEVM -> Arbitrum via LayerZero OFT.
|
|
1323
|
+
|
|
1324
|
+
Notes:
|
|
1325
|
+
- Uses HyperEVM chain id (999) for the transaction.
|
|
1326
|
+
- `amount_wei` is in 1e18 (native HYPE).
|
|
1327
|
+
- The OFT bridge requires `msg.value = amount + nativeFee`.
|
|
1328
|
+
- Amount must be rounded down to `decimalConversionRate()`.
|
|
1329
|
+
- If `max_value_wei` is provided, clamps amount so that (amount + fee) <= max_value_wei.
|
|
1330
|
+
"""
|
|
1331
|
+
if amount_wei <= 0:
|
|
1332
|
+
return True, {"status": "no_op", "amount_wei": 0}
|
|
1333
|
+
|
|
1334
|
+
if self.simulation:
|
|
1335
|
+
return True, {
|
|
1336
|
+
"status": "simulated",
|
|
1337
|
+
"amount_wei": int(amount_wei),
|
|
1338
|
+
"dst_eid": int(dst_eid),
|
|
1339
|
+
"to": to_address or self.user_address,
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
if not self.sign_callback:
|
|
1343
|
+
return False, {"error": "sign_callback not configured"}
|
|
1344
|
+
|
|
1345
|
+
sender = from_address or self.user_address
|
|
1346
|
+
recipient = to_address or self.user_address
|
|
1347
|
+
if not sender or not recipient:
|
|
1348
|
+
return False, {"error": "from_address/to_address not configured"}
|
|
1349
|
+
|
|
1350
|
+
try:
|
|
1351
|
+
async with web3_from_chain_id(CHAIN_ID_HYPEREVM) as w3:
|
|
1352
|
+
contract = w3.eth.contract(
|
|
1353
|
+
address=w3.to_checksum_address(HYPE_OFT_ADDRESS),
|
|
1354
|
+
abi=HYPE_OFT_ABI,
|
|
1355
|
+
)
|
|
1356
|
+
|
|
1357
|
+
conversion_rate = int(
|
|
1358
|
+
await contract.functions.decimalConversionRate().call()
|
|
1359
|
+
)
|
|
1360
|
+
if conversion_rate > 0:
|
|
1361
|
+
amount_wei = (int(amount_wei) // conversion_rate) * conversion_rate
|
|
1362
|
+
else:
|
|
1363
|
+
amount_wei = int(amount_wei)
|
|
1364
|
+
|
|
1365
|
+
if amount_wei <= 0:
|
|
1366
|
+
return True, {"status": "no_op", "amount_wei": 0}
|
|
1367
|
+
|
|
1368
|
+
to_bytes32 = self._pad_address_bytes32(recipient)
|
|
1369
|
+
|
|
1370
|
+
def _send_params(amount_ld: int) -> tuple[Any, ...]:
|
|
1371
|
+
return (
|
|
1372
|
+
int(dst_eid),
|
|
1373
|
+
to_bytes32,
|
|
1374
|
+
int(amount_ld),
|
|
1375
|
+
int(min_amount_wei),
|
|
1376
|
+
b"",
|
|
1377
|
+
b"",
|
|
1378
|
+
b"",
|
|
1379
|
+
)
|
|
1380
|
+
|
|
1381
|
+
send_params = _send_params(int(amount_wei))
|
|
1382
|
+
fee = await contract.functions.quoteSend(send_params, False).call()
|
|
1383
|
+
native_fee_wei = int(fee[0])
|
|
1384
|
+
lz_token_fee_wei = int(fee[1])
|
|
1385
|
+
|
|
1386
|
+
if max_value_wei is not None:
|
|
1387
|
+
max_send_amount_wei = max(0, int(max_value_wei) - native_fee_wei)
|
|
1388
|
+
if conversion_rate > 0:
|
|
1389
|
+
max_send_amount_wei = (
|
|
1390
|
+
max_send_amount_wei // conversion_rate
|
|
1391
|
+
) * conversion_rate
|
|
1392
|
+
if amount_wei > max_send_amount_wei:
|
|
1393
|
+
amount_wei = int(max_send_amount_wei)
|
|
1394
|
+
if amount_wei <= 0:
|
|
1395
|
+
return False, {
|
|
1396
|
+
"error": "Insufficient balance to cover OFT fee",
|
|
1397
|
+
"native_fee_wei": native_fee_wei,
|
|
1398
|
+
"max_value_wei": int(max_value_wei),
|
|
1399
|
+
}
|
|
1400
|
+
send_params = _send_params(int(amount_wei))
|
|
1401
|
+
fee = await contract.functions.quoteSend(
|
|
1402
|
+
send_params, False
|
|
1403
|
+
).call()
|
|
1404
|
+
native_fee_wei = int(fee[0])
|
|
1405
|
+
lz_token_fee_wei = int(fee[1])
|
|
1406
|
+
|
|
1407
|
+
total_value_wei = int(amount_wei) + int(native_fee_wei)
|
|
1408
|
+
if max_value_wei is not None and total_value_wei > int(max_value_wei):
|
|
1409
|
+
return False, {
|
|
1410
|
+
"error": "Insufficient balance after fee quote",
|
|
1411
|
+
"amount_wei": int(amount_wei),
|
|
1412
|
+
"native_fee_wei": int(native_fee_wei),
|
|
1413
|
+
"total_value_wei": int(total_value_wei),
|
|
1414
|
+
"max_value_wei": int(max_value_wei),
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
tx = await encode_call(
|
|
1418
|
+
target=HYPE_OFT_ADDRESS,
|
|
1419
|
+
abi=HYPE_OFT_ABI,
|
|
1420
|
+
fn_name="send",
|
|
1421
|
+
args=[
|
|
1422
|
+
send_params,
|
|
1423
|
+
(int(native_fee_wei), int(lz_token_fee_wei)),
|
|
1424
|
+
to_checksum_address(sender),
|
|
1425
|
+
],
|
|
1426
|
+
from_address=sender,
|
|
1427
|
+
chain_id=CHAIN_ID_HYPEREVM,
|
|
1428
|
+
value=int(total_value_wei),
|
|
1429
|
+
)
|
|
1430
|
+
tx_hash = await send_transaction(
|
|
1431
|
+
tx, self.sign_callback, wait_for_receipt=True
|
|
1432
|
+
)
|
|
1433
|
+
return True, {
|
|
1434
|
+
"status": "ok",
|
|
1435
|
+
"tx_hash": tx_hash,
|
|
1436
|
+
"amount_wei": int(amount_wei),
|
|
1437
|
+
"native_fee_wei": int(native_fee_wei),
|
|
1438
|
+
"lz_token_fee_wei": int(lz_token_fee_wei),
|
|
1439
|
+
"total_value_wei": int(total_value_wei),
|
|
1440
|
+
"dst_eid": int(dst_eid),
|
|
1441
|
+
"to": recipient,
|
|
1442
|
+
"from": sender,
|
|
1443
|
+
"layerzeroscan": f"https://layerzeroscan.com/tx/{tx_hash}",
|
|
1444
|
+
}
|
|
1445
|
+
except Exception as exc: # noqa: BLE001
|
|
1446
|
+
return False, {"error": str(exc)}
|
|
1447
|
+
|
|
1448
|
+
async def close_positions_except(
|
|
1449
|
+
self,
|
|
1450
|
+
*,
|
|
1451
|
+
keep_market_id: int,
|
|
1452
|
+
token_id: int = 3,
|
|
1453
|
+
market_ids: list[int] | None = None,
|
|
1454
|
+
best_effort: bool = True,
|
|
1455
|
+
) -> tuple[bool, dict[str, Any]]:
|
|
1456
|
+
"""Close all Boros positions except `keep_market_id` (best-effort by default)."""
|
|
1457
|
+
if self.simulation:
|
|
1458
|
+
return True, {
|
|
1459
|
+
"status": "simulated",
|
|
1460
|
+
"keep_market_id": int(keep_market_id),
|
|
1461
|
+
"markets": market_ids or [],
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
if market_ids is None:
|
|
1465
|
+
ok_pos, positions = await self.get_active_positions()
|
|
1466
|
+
if not ok_pos:
|
|
1467
|
+
return False, {"error": f"Failed to get positions: {positions}"}
|
|
1468
|
+
market_ids = sorted(
|
|
1469
|
+
{
|
|
1470
|
+
int(p.get("marketId"))
|
|
1471
|
+
for p in positions
|
|
1472
|
+
if p.get("marketId") is not None
|
|
1473
|
+
}
|
|
1474
|
+
)
|
|
1475
|
+
|
|
1476
|
+
results: list[dict[str, Any]] = []
|
|
1477
|
+
failures: list[dict[str, Any]] = []
|
|
1478
|
+
for mid in market_ids:
|
|
1479
|
+
if int(mid) == int(keep_market_id):
|
|
1480
|
+
continue
|
|
1481
|
+
ok_close, res_close = await self.close_positions_market(
|
|
1482
|
+
int(mid), token_id=int(token_id)
|
|
1483
|
+
)
|
|
1484
|
+
entry = {"market_id": int(mid), "ok": bool(ok_close), "res": res_close}
|
|
1485
|
+
results.append(entry)
|
|
1486
|
+
if not ok_close:
|
|
1487
|
+
failures.append(entry)
|
|
1488
|
+
if not best_effort:
|
|
1489
|
+
return False, {
|
|
1490
|
+
"error": f"Failed to close position for market {mid}",
|
|
1491
|
+
"results": results,
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
return True, {"status": "ok", "results": results, "failures": failures}
|
|
1495
|
+
|
|
1496
|
+
async def ensure_position_size_yu(
|
|
1497
|
+
self,
|
|
1498
|
+
*,
|
|
1499
|
+
market_id: int,
|
|
1500
|
+
token_id: int,
|
|
1501
|
+
target_size_yu: float,
|
|
1502
|
+
tif: str = "IOC",
|
|
1503
|
+
min_resize_excess_usd: float | None = None,
|
|
1504
|
+
yu_to_usd: float | None = None,
|
|
1505
|
+
) -> tuple[bool, dict[str, Any]]:
|
|
1506
|
+
"""Ensure the Boros position size (YU) for a market.
|
|
1507
|
+
|
|
1508
|
+
- Uses `place_rate_order(... side="short")` to increase the position.
|
|
1509
|
+
- Uses `close_positions_market(..., size_yu_wei=...)` to decrease it.
|
|
1510
|
+
- If `min_resize_excess_usd` is provided, uses `yu_to_usd` to skip small resizes.
|
|
1511
|
+
"""
|
|
1512
|
+
if self.simulation:
|
|
1513
|
+
return True, {
|
|
1514
|
+
"status": "simulated",
|
|
1515
|
+
"market_id": int(market_id),
|
|
1516
|
+
"token_id": int(token_id),
|
|
1517
|
+
"target_size_yu": float(target_size_yu),
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
ok_pos, positions = await self.get_active_positions(market_id=int(market_id))
|
|
1521
|
+
if not ok_pos:
|
|
1522
|
+
return False, {"error": f"Failed to get positions: {positions}"}
|
|
1523
|
+
|
|
1524
|
+
if positions:
|
|
1525
|
+
current_size_yu = abs(float(positions[0].get("size", 0) or 0.0))
|
|
1526
|
+
else:
|
|
1527
|
+
current_size_yu = 0.0
|
|
1528
|
+
|
|
1529
|
+
diff_yu = float(target_size_yu) - float(current_size_yu)
|
|
1530
|
+
diff_abs_yu = abs(diff_yu)
|
|
1531
|
+
|
|
1532
|
+
if min_resize_excess_usd is not None:
|
|
1533
|
+
if yu_to_usd is None or yu_to_usd <= 0:
|
|
1534
|
+
return False, {
|
|
1535
|
+
"error": "yu_to_usd required when min_resize_excess_usd is set",
|
|
1536
|
+
"yu_to_usd": yu_to_usd,
|
|
1537
|
+
}
|
|
1538
|
+
diff_usd_equiv = diff_abs_yu * float(yu_to_usd)
|
|
1539
|
+
if diff_usd_equiv < float(min_resize_excess_usd):
|
|
1540
|
+
return True, {
|
|
1541
|
+
"status": "ok",
|
|
1542
|
+
"action": "no_op",
|
|
1543
|
+
"market_id": int(market_id),
|
|
1544
|
+
"token_id": int(token_id),
|
|
1545
|
+
"current_size_yu": float(current_size_yu),
|
|
1546
|
+
"target_size_yu": float(target_size_yu),
|
|
1547
|
+
"diff_yu": float(diff_yu),
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
if diff_abs_yu < 1e-9:
|
|
1551
|
+
return True, {
|
|
1552
|
+
"status": "ok",
|
|
1553
|
+
"action": "no_op",
|
|
1554
|
+
"market_id": int(market_id),
|
|
1555
|
+
"token_id": int(token_id),
|
|
1556
|
+
"current_size_yu": float(current_size_yu),
|
|
1557
|
+
"target_size_yu": float(target_size_yu),
|
|
1558
|
+
"diff_yu": float(diff_yu),
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
size_yu_wei = int(diff_abs_yu * 1e18)
|
|
1562
|
+
|
|
1563
|
+
if diff_yu > 0:
|
|
1564
|
+
ok_open, res_open = await self.place_rate_order(
|
|
1565
|
+
market_id=int(market_id),
|
|
1566
|
+
token_id=int(token_id),
|
|
1567
|
+
size_yu_wei=int(size_yu_wei),
|
|
1568
|
+
side="short",
|
|
1569
|
+
tif=tif,
|
|
1570
|
+
)
|
|
1571
|
+
if not ok_open:
|
|
1572
|
+
return False, {
|
|
1573
|
+
"error": f"Failed to open/increase position: {res_open}",
|
|
1574
|
+
"market_id": int(market_id),
|
|
1575
|
+
}
|
|
1576
|
+
return True, {
|
|
1577
|
+
"status": "ok",
|
|
1578
|
+
"action": "increase_short",
|
|
1579
|
+
"market_id": int(market_id),
|
|
1580
|
+
"token_id": int(token_id),
|
|
1581
|
+
"current_size_yu": float(current_size_yu),
|
|
1582
|
+
"target_size_yu": float(target_size_yu),
|
|
1583
|
+
"diff_yu": float(diff_yu),
|
|
1584
|
+
"tx": res_open,
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
ok_close, res_close = await self.close_positions_market(
|
|
1588
|
+
market_id=int(market_id),
|
|
1589
|
+
token_id=int(token_id),
|
|
1590
|
+
size_yu_wei=int(size_yu_wei),
|
|
1591
|
+
)
|
|
1592
|
+
if not ok_close:
|
|
1593
|
+
return False, {
|
|
1594
|
+
"error": f"Failed to close/decrease position: {res_close}",
|
|
1595
|
+
"market_id": int(market_id),
|
|
1596
|
+
}
|
|
1597
|
+
return True, {
|
|
1598
|
+
"status": "ok",
|
|
1599
|
+
"action": "decrease",
|
|
1600
|
+
"market_id": int(market_id),
|
|
1601
|
+
"token_id": int(token_id),
|
|
1602
|
+
"current_size_yu": float(current_size_yu),
|
|
1603
|
+
"target_size_yu": float(target_size_yu),
|
|
1604
|
+
"diff_yu": float(diff_yu),
|
|
1605
|
+
"tx": res_close,
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1177
1608
|
async def place_rate_order(
|
|
1178
1609
|
self,
|
|
1179
1610
|
*,
|
{wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/client.py
RENAMED
|
@@ -250,10 +250,11 @@ class BorosClient:
|
|
|
250
250
|
|
|
251
251
|
Args:
|
|
252
252
|
token_id: Boros token ID (e.g., 3 for USDT).
|
|
253
|
-
amount_wei: Amount in
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
253
|
+
amount_wei: Amount in NATIVE token decimals (despite the param name).
|
|
254
|
+
Example: USDT has 6 decimals, so 1 USDT = 1_000_000.
|
|
255
|
+
market_id: Target market ID.
|
|
256
|
+
user_address: User wallet address.
|
|
257
|
+
account_id: Boros account ID (0 = cross margin).
|
|
257
258
|
|
|
258
259
|
Returns:
|
|
259
260
|
Calldata dictionary with 'to', 'data', 'value' fields.
|
|
@@ -283,7 +284,8 @@ class BorosClient:
|
|
|
283
284
|
|
|
284
285
|
Args:
|
|
285
286
|
token_id: Boros token ID.
|
|
286
|
-
amount_wei: Amount in
|
|
287
|
+
amount_wei: Amount in NATIVE token decimals (despite the param name).
|
|
288
|
+
Example: USDT has 6 decimals, so 1 USDT = 1_000_000.
|
|
287
289
|
user_address: User wallet address.
|
|
288
290
|
account_id: Account ID.
|
|
289
291
|
|