wayfinder-paths 0.1.21__tar.gz → 0.1.23__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.
Potentially problematic release.
This version of wayfinder-paths might be problematic. Click here for more details.
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/PKG-INFO +3 -4
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/README.md +1 -1
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/pyproject.toml +2 -2
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/__init__.py +0 -4
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/balance_adapter/README.md +0 -1
- wayfinder_paths-0.1.23/wayfinder_paths/adapters/balance_adapter/adapter.py +179 -0
- wayfinder_paths-0.1.23/wayfinder_paths/adapters/balance_adapter/test_adapter.py +90 -0
- wayfinder_paths-0.1.23/wayfinder_paths/adapters/brap_adapter/README.md +71 -0
- wayfinder_paths-0.1.23/wayfinder_paths/adapters/brap_adapter/adapter.py +305 -0
- wayfinder_paths-0.1.23/wayfinder_paths/adapters/brap_adapter/examples.json +67 -0
- wayfinder_paths-0.1.23/wayfinder_paths/adapters/brap_adapter/test_adapter.py +87 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/hyperlend_adapter/adapter.py +39 -86
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +5 -1
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +6 -5
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/ledger_adapter/README.md +4 -1
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/ledger_adapter/adapter.py +3 -3
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/moonwell_adapter/adapter.py +108 -198
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +37 -23
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/token_adapter/adapter.py +14 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/__init__.py +0 -3
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/clients/BRAPClient.py +3 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/clients/ClientManager.py +0 -7
- wayfinder_paths-0.1.23/wayfinder_paths/core/clients/LedgerClient.py +344 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/clients/WayfinderClient.py +0 -1
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/clients/__init__.py +0 -5
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/clients/protocols.py +0 -13
- wayfinder_paths-0.1.23/wayfinder_paths/core/config.py +39 -0
- wayfinder_paths-0.1.23/wayfinder_paths/core/constants/__init__.py +73 -0
- wayfinder_paths-0.1.23/wayfinder_paths/core/constants/base.py +24 -0
- wayfinder_paths-0.1.23/wayfinder_paths/core/constants/chains.py +36 -0
- wayfinder_paths-0.1.23/wayfinder_paths/core/constants/contracts.py +39 -0
- wayfinder_paths-0.1.23/wayfinder_paths/core/constants/tokens.py +9 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/strategies/Strategy.py +0 -10
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/utils/evm_helpers.py +5 -15
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/utils/tokens.py +28 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/utils/transaction.py +13 -7
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/utils/web3.py +5 -3
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/policies/enso.py +1 -2
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/policies/hyper_evm.py +6 -3
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/policies/hyperlend.py +1 -2
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/policies/moonwell.py +12 -7
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/policies/prjx.py +1 -3
- wayfinder_paths-0.1.23/wayfinder_paths/run_strategy.py +146 -0
- wayfinder_paths-0.1.23/wayfinder_paths/strategies/basis_trading_strategy/constants.py +3 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/basis_trading_strategy/strategy.py +19 -14
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +12 -11
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +20 -33
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +21 -18
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +69 -130
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +32 -42
- wayfinder_paths-0.1.21/wayfinder_paths/adapters/balance_adapter/adapter.py +0 -283
- wayfinder_paths-0.1.21/wayfinder_paths/adapters/balance_adapter/test_adapter.py +0 -162
- wayfinder_paths-0.1.21/wayfinder_paths/adapters/brap_adapter/README.md +0 -124
- wayfinder_paths-0.1.21/wayfinder_paths/adapters/brap_adapter/adapter.py +0 -694
- wayfinder_paths-0.1.21/wayfinder_paths/adapters/brap_adapter/examples.json +0 -186
- wayfinder_paths-0.1.21/wayfinder_paths/adapters/brap_adapter/test_adapter.py +0 -315
- wayfinder_paths-0.1.21/wayfinder_paths/core/clients/LedgerClient.py +0 -320
- wayfinder_paths-0.1.21/wayfinder_paths/core/clients/WalletClient.py +0 -41
- wayfinder_paths-0.1.21/wayfinder_paths/core/config.py +0 -203
- wayfinder_paths-0.1.21/wayfinder_paths/core/constants/__init__.py +0 -17
- wayfinder_paths-0.1.21/wayfinder_paths/core/constants/base.py +0 -38
- wayfinder_paths-0.1.21/wayfinder_paths/core/engine/StrategyJob.py +0 -110
- wayfinder_paths-0.1.21/wayfinder_paths/core/services/test_local_evm_txn.py +0 -145
- wayfinder_paths-0.1.21/wayfinder_paths/run_strategy.py +0 -349
- wayfinder_paths-0.1.21/wayfinder_paths/strategies/basis_trading_strategy/constants.py +0 -1
- wayfinder_paths-0.1.21/wayfinder_paths/templates/adapter/README.md +0 -150
- wayfinder_paths-0.1.21/wayfinder_paths/templates/adapter/adapter.py +0 -16
- wayfinder_paths-0.1.21/wayfinder_paths/templates/adapter/examples.json +0 -8
- wayfinder_paths-0.1.21/wayfinder_paths/templates/adapter/test_adapter.py +0 -30
- wayfinder_paths-0.1.21/wayfinder_paths/templates/strategy/README.md +0 -186
- wayfinder_paths-0.1.21/wayfinder_paths/templates/strategy/examples.json +0 -11
- wayfinder_paths-0.1.21/wayfinder_paths/templates/strategy/strategy.py +0 -35
- wayfinder_paths-0.1.21/wayfinder_paths/templates/strategy/test_strategy.py +0 -166
- wayfinder_paths-0.1.21/wayfinder_paths/tests/test_smoke_manifest.py +0 -63
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/LICENSE +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/balance_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/brap_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/hyperlend_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/hyperliquid_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/hyperliquid_adapter/executor.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/hyperliquid_adapter/test_executor.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/hyperliquid_adapter/utils.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/ledger_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/ledger_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/ledger_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/moonwell_adapter/README.md +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/moonwell_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/pool_adapter/README.md +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/pool_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/pool_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/pool_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/pool_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/token_adapter/README.md +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/token_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/token_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/adapters/token_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/conftest.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/adapters/BaseAdapter.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/adapters/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/adapters/models.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/analytics/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/analytics/bootstrap.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/analytics/stats.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/analytics/test_analytics.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/clients/HyperlendClient.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/clients/PoolClient.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/clients/TokenClient.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/constants/erc20_abi.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/constants/hyperlend_abi.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/constants/moonwell_abi.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/strategies/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/strategies/base.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/strategies/descriptors.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/utils/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/core/utils/wallets.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/policies/erc20.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/policies/evm.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/policies/hyperliquid.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/policies/util.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/scripts/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/scripts/create_strategy.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/scripts/make_wallets.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/basis_trading_strategy/README.md +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/basis_trading_strategy/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/basis_trading_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/basis_trading_strategy/snapshot_mixin.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/basis_trading_strategy/types.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/README.md +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/strategies/stablecoin_yield_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/tests/__init__.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/tests/test_test_coverage.py +0 -0
- {wayfinder_paths-0.1.21 → wayfinder_paths-0.1.23}/wayfinder_paths/tests/test_utils.py +0 -0
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: wayfinder-paths
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.23
|
|
4
4
|
Summary: Wayfinder Path: strategies and adapters
|
|
5
5
|
Author: Wayfinder
|
|
6
6
|
Author-email: dev@wayfinder.ai
|
|
7
7
|
Requires-Python: >=3.12,<4.0
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
11
10
|
Requires-Dist: aiohttp (>=3.13.0,<4.0.0)
|
|
12
11
|
Requires-Dist: eth-account (>=0.13.7,<0.14.0)
|
|
13
12
|
Requires-Dist: httpx (>=0.28.1,<0.29.0)
|
|
14
|
-
Requires-Dist: hyperliquid-
|
|
13
|
+
Requires-Dist: hyperliquid-felix
|
|
15
14
|
Requires-Dist: loguru (>=0.7.3,<0.8.0)
|
|
16
15
|
Requires-Dist: numpy (>=1.26.0,<2.0.0)
|
|
17
16
|
Requires-Dist: pandas (>=2.2.0,<3.0.0)
|
|
@@ -98,7 +97,7 @@ Strategy Layer - Trading logic (deposit, update, withdraw, exit)
|
|
|
98
97
|
↓
|
|
99
98
|
Adapter Layer - Protocol integrations (BalanceAdapter, PoolAdapter, etc.)
|
|
100
99
|
↓
|
|
101
|
-
Client Layer - API wrappers (TokenClient,
|
|
100
|
+
Client Layer - API wrappers (TokenClient, PoolClient, LedgerClient, etc.)
|
|
102
101
|
↓
|
|
103
102
|
Network - RPCs, Wayfinder API, external services
|
|
104
103
|
```
|
|
@@ -76,7 +76,7 @@ Strategy Layer - Trading logic (deposit, update, withdraw, exit)
|
|
|
76
76
|
↓
|
|
77
77
|
Adapter Layer - Protocol integrations (BalanceAdapter, PoolAdapter, etc.)
|
|
78
78
|
↓
|
|
79
|
-
Client Layer - API wrappers (TokenClient,
|
|
79
|
+
Client Layer - API wrappers (TokenClient, PoolClient, LedgerClient, etc.)
|
|
80
80
|
↓
|
|
81
81
|
Network - RPCs, Wayfinder API, external services
|
|
82
82
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "wayfinder-paths"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.23"
|
|
4
4
|
description = "Wayfinder Path: strategies and adapters"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = ["Wayfinder <dev@wayfinder.ai>"]
|
|
@@ -19,7 +19,7 @@ eth-account = "^0.13.7"
|
|
|
19
19
|
aiohttp = "^3.13.0"
|
|
20
20
|
numpy = "^1.26.0"
|
|
21
21
|
pandas = "^2.2.0"
|
|
22
|
-
hyperliquid-
|
|
22
|
+
hyperliquid-felix = "*"
|
|
23
23
|
|
|
24
24
|
[tool.poetry.group.dev.dependencies]
|
|
25
25
|
pytest = "^8.4.2"
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
__version__ = "0.1.0"
|
|
2
2
|
|
|
3
|
-
# Re-export commonly used items for convenience
|
|
4
3
|
from wayfinder_paths.core import (
|
|
5
4
|
BaseAdapter,
|
|
6
|
-
LiquidationResult,
|
|
7
5
|
StatusDict,
|
|
8
6
|
StatusTuple,
|
|
9
7
|
Strategy,
|
|
10
|
-
StrategyJob,
|
|
11
8
|
)
|
|
12
9
|
|
|
13
10
|
__all__ = [
|
|
@@ -16,5 +13,4 @@ __all__ = [
|
|
|
16
13
|
"Strategy",
|
|
17
14
|
"StatusDict",
|
|
18
15
|
"StatusTuple",
|
|
19
|
-
"StrategyJob",
|
|
20
16
|
]
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from wayfinder_paths.adapters.ledger_adapter.adapter import LedgerAdapter
|
|
4
|
+
from wayfinder_paths.adapters.token_adapter.adapter import TokenAdapter
|
|
5
|
+
from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
|
|
6
|
+
from wayfinder_paths.core.clients.TokenClient import TokenClient
|
|
7
|
+
from wayfinder_paths.core.utils.evm_helpers import resolve_chain_id
|
|
8
|
+
from wayfinder_paths.core.utils.tokens import build_send_transaction, get_token_balance
|
|
9
|
+
from wayfinder_paths.core.utils.transaction import send_transaction
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BalanceAdapter(BaseAdapter):
|
|
13
|
+
adapter_type = "BALANCE"
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
config: dict[str, Any],
|
|
18
|
+
main_wallet_signing_callback=None,
|
|
19
|
+
strategy_wallet_signing_callback=None,
|
|
20
|
+
):
|
|
21
|
+
super().__init__("balance", config)
|
|
22
|
+
self.main_wallet_signing_callback = main_wallet_signing_callback
|
|
23
|
+
self.strategy_wallet_signing_callback = strategy_wallet_signing_callback
|
|
24
|
+
self.token_client = TokenClient()
|
|
25
|
+
self.token_adapter = TokenAdapter()
|
|
26
|
+
self.ledger_adapter = LedgerAdapter()
|
|
27
|
+
|
|
28
|
+
async def get_balance(
|
|
29
|
+
self,
|
|
30
|
+
*,
|
|
31
|
+
wallet_address: str,
|
|
32
|
+
token_id: str | None = None,
|
|
33
|
+
token_address: str | None = None,
|
|
34
|
+
chain_id: int | None = None,
|
|
35
|
+
) -> tuple[bool, int | str]:
|
|
36
|
+
try:
|
|
37
|
+
if token_id and not token_address:
|
|
38
|
+
token_info = await self.token_client.get_token_details(token_id)
|
|
39
|
+
token_address = token_info["address"]
|
|
40
|
+
chain_id = chain_id or resolve_chain_id(token_info)
|
|
41
|
+
balance = await get_token_balance(token_address, chain_id, wallet_address)
|
|
42
|
+
return True, balance
|
|
43
|
+
except Exception as e:
|
|
44
|
+
return False, str(e)
|
|
45
|
+
|
|
46
|
+
async def move_from_main_wallet_to_strategy_wallet(
|
|
47
|
+
self,
|
|
48
|
+
token_id: str,
|
|
49
|
+
amount: float,
|
|
50
|
+
strategy_name: str = "unknown",
|
|
51
|
+
skip_ledger: bool = False,
|
|
52
|
+
) -> tuple[bool, str]:
|
|
53
|
+
return await self._move_between_wallets(
|
|
54
|
+
token_id=token_id,
|
|
55
|
+
amount=amount,
|
|
56
|
+
from_wallet=self.config["main_wallet"],
|
|
57
|
+
to_wallet=self.config["strategy_wallet"],
|
|
58
|
+
ledger_method=self.ledger_adapter.record_deposit
|
|
59
|
+
if not skip_ledger
|
|
60
|
+
else None,
|
|
61
|
+
ledger_wallet="to",
|
|
62
|
+
strategy_name=strategy_name,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
async def move_from_strategy_wallet_to_main_wallet(
|
|
66
|
+
self,
|
|
67
|
+
token_id: str,
|
|
68
|
+
amount: float,
|
|
69
|
+
strategy_name: str = "unknown",
|
|
70
|
+
skip_ledger: bool = False,
|
|
71
|
+
) -> tuple[bool, str]:
|
|
72
|
+
return await self._move_between_wallets(
|
|
73
|
+
token_id=token_id,
|
|
74
|
+
amount=amount,
|
|
75
|
+
from_wallet=self.config["strategy_wallet"],
|
|
76
|
+
to_wallet=self.config["main_wallet"],
|
|
77
|
+
ledger_method=self.ledger_adapter.record_withdrawal
|
|
78
|
+
if not skip_ledger
|
|
79
|
+
else None,
|
|
80
|
+
ledger_wallet="from",
|
|
81
|
+
strategy_name=strategy_name,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
async def send_to_address(
|
|
85
|
+
self,
|
|
86
|
+
token_id: str,
|
|
87
|
+
amount: int,
|
|
88
|
+
from_wallet: dict[str, Any],
|
|
89
|
+
to_address: str,
|
|
90
|
+
signing_callback,
|
|
91
|
+
) -> tuple[bool, str]:
|
|
92
|
+
token_info = await self.token_client.get_token_details(token_id)
|
|
93
|
+
chain_id = resolve_chain_id(token_info)
|
|
94
|
+
tx = await build_send_transaction(
|
|
95
|
+
from_address=from_wallet["address"],
|
|
96
|
+
to_address=to_address,
|
|
97
|
+
token_address=token_info["address"],
|
|
98
|
+
chain_id=chain_id,
|
|
99
|
+
amount=amount,
|
|
100
|
+
)
|
|
101
|
+
tx_hash = await send_transaction(tx, signing_callback)
|
|
102
|
+
return True, tx_hash
|
|
103
|
+
|
|
104
|
+
async def _move_between_wallets(
|
|
105
|
+
self,
|
|
106
|
+
*,
|
|
107
|
+
token_id: str,
|
|
108
|
+
amount: float,
|
|
109
|
+
from_wallet: dict[str, Any],
|
|
110
|
+
to_wallet: dict[str, Any],
|
|
111
|
+
ledger_method,
|
|
112
|
+
ledger_wallet: str,
|
|
113
|
+
strategy_name: str,
|
|
114
|
+
) -> tuple[bool, str]:
|
|
115
|
+
token_info = await self.token_client.get_token_details(token_id)
|
|
116
|
+
chain_id = resolve_chain_id(token_info)
|
|
117
|
+
decimals = token_info.get("decimals", 18)
|
|
118
|
+
raw_amount = int(amount * (10**decimals))
|
|
119
|
+
|
|
120
|
+
transaction = await build_send_transaction(
|
|
121
|
+
from_address=from_wallet["address"],
|
|
122
|
+
to_address=to_wallet["address"],
|
|
123
|
+
token_address=token_info["address"],
|
|
124
|
+
chain_id=chain_id,
|
|
125
|
+
amount=raw_amount,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
main_address = self.config.get("main_wallet", {}).get("address", "").lower()
|
|
129
|
+
callback = (
|
|
130
|
+
self.main_wallet_signing_callback
|
|
131
|
+
if from_wallet["address"].lower() == main_address
|
|
132
|
+
else self.strategy_wallet_signing_callback
|
|
133
|
+
)
|
|
134
|
+
tx_hash = await send_transaction(transaction, callback)
|
|
135
|
+
|
|
136
|
+
if ledger_method:
|
|
137
|
+
wallet_for_ledger = (
|
|
138
|
+
from_wallet["address"]
|
|
139
|
+
if ledger_wallet == "from"
|
|
140
|
+
else to_wallet["address"]
|
|
141
|
+
)
|
|
142
|
+
await self._record_ledger_entry(
|
|
143
|
+
ledger_method, wallet_for_ledger, token_info, amount, strategy_name
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
return True, tx_hash
|
|
147
|
+
|
|
148
|
+
async def _record_ledger_entry(
|
|
149
|
+
self,
|
|
150
|
+
ledger_method,
|
|
151
|
+
wallet_address: str,
|
|
152
|
+
token_info: dict[str, Any],
|
|
153
|
+
amount: float,
|
|
154
|
+
strategy_name: str,
|
|
155
|
+
) -> None:
|
|
156
|
+
try:
|
|
157
|
+
chain_id = resolve_chain_id(token_info)
|
|
158
|
+
token_id = token_info.get("token_id")
|
|
159
|
+
usd_value = (
|
|
160
|
+
await self.token_adapter.get_amount_usd(
|
|
161
|
+
token_info.get("token_id"), amount, decimals=0
|
|
162
|
+
)
|
|
163
|
+
or 0.0
|
|
164
|
+
)
|
|
165
|
+
await ledger_method(
|
|
166
|
+
wallet_address=wallet_address,
|
|
167
|
+
chain_id=chain_id,
|
|
168
|
+
token_address=token_info.get("address"),
|
|
169
|
+
token_amount=str(amount),
|
|
170
|
+
usd_value=usd_value,
|
|
171
|
+
data={
|
|
172
|
+
"token_id": token_id,
|
|
173
|
+
"amount": str(amount),
|
|
174
|
+
"usd_value": usd_value,
|
|
175
|
+
},
|
|
176
|
+
strategy_name=strategy_name,
|
|
177
|
+
)
|
|
178
|
+
except Exception as exc:
|
|
179
|
+
self.logger.warning(f"Ledger entry failed: {exc}", wallet=wallet_address)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
from unittest.mock import AsyncMock, patch
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from wayfinder_paths.adapters.balance_adapter.adapter import BalanceAdapter
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestBalanceAdapter:
|
|
9
|
+
@pytest.fixture
|
|
10
|
+
def mock_token_client(self):
|
|
11
|
+
return AsyncMock()
|
|
12
|
+
|
|
13
|
+
@pytest.fixture
|
|
14
|
+
def adapter(self, mock_token_client):
|
|
15
|
+
with patch(
|
|
16
|
+
"wayfinder_paths.adapters.balance_adapter.adapter.TokenClient",
|
|
17
|
+
return_value=mock_token_client,
|
|
18
|
+
):
|
|
19
|
+
return BalanceAdapter(config={})
|
|
20
|
+
|
|
21
|
+
@pytest.mark.asyncio
|
|
22
|
+
async def test_health_check(self, adapter):
|
|
23
|
+
health = await adapter.health_check()
|
|
24
|
+
assert isinstance(health, dict)
|
|
25
|
+
assert health.get("status") in {"healthy", "unhealthy", "error"}
|
|
26
|
+
|
|
27
|
+
@pytest.mark.asyncio
|
|
28
|
+
async def test_connect(self, adapter):
|
|
29
|
+
ok = await adapter.connect()
|
|
30
|
+
assert isinstance(ok, bool)
|
|
31
|
+
|
|
32
|
+
def test_adapter_type(self, adapter):
|
|
33
|
+
assert adapter.adapter_type == "BALANCE"
|
|
34
|
+
|
|
35
|
+
@pytest.mark.asyncio
|
|
36
|
+
async def test_get_balance_with_token_id(self, adapter, mock_token_client):
|
|
37
|
+
mock_token_client.get_token_details = AsyncMock(
|
|
38
|
+
return_value={
|
|
39
|
+
"token_id": "usd-coin-base",
|
|
40
|
+
"address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
41
|
+
"chain": {"id": 8453, "code": "base"},
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
with patch(
|
|
46
|
+
"wayfinder_paths.adapters.balance_adapter.adapter.get_token_balance",
|
|
47
|
+
new_callable=AsyncMock,
|
|
48
|
+
return_value=1000000,
|
|
49
|
+
) as mock_get_balance:
|
|
50
|
+
success, balance = await adapter.get_balance(
|
|
51
|
+
token_id="usd-coin-base",
|
|
52
|
+
wallet_address="0xWallet",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
assert success
|
|
56
|
+
assert balance == 1000000
|
|
57
|
+
mock_token_client.get_token_details.assert_called_once_with("usd-coin-base")
|
|
58
|
+
mock_get_balance.assert_called_once_with(
|
|
59
|
+
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", 8453, "0xWallet"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
@pytest.mark.asyncio
|
|
63
|
+
async def test_get_balance_with_token_address(self, adapter, mock_token_client):
|
|
64
|
+
with patch(
|
|
65
|
+
"wayfinder_paths.adapters.balance_adapter.adapter.get_token_balance",
|
|
66
|
+
new_callable=AsyncMock,
|
|
67
|
+
return_value=5000000,
|
|
68
|
+
) as mock_get_balance:
|
|
69
|
+
success, balance = await adapter.get_balance(
|
|
70
|
+
token_address="0xTokenAddress",
|
|
71
|
+
wallet_address="0xWallet",
|
|
72
|
+
chain_id=8453,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
assert success
|
|
76
|
+
assert balance == 5000000
|
|
77
|
+
mock_get_balance.assert_called_once_with("0xTokenAddress", 8453, "0xWallet")
|
|
78
|
+
mock_token_client.get_token_details.assert_not_called()
|
|
79
|
+
|
|
80
|
+
@pytest.mark.asyncio
|
|
81
|
+
async def test_get_balance_token_not_found(self, adapter, mock_token_client):
|
|
82
|
+
mock_token_client.get_token_details = AsyncMock(return_value=None)
|
|
83
|
+
|
|
84
|
+
success, error = await adapter.get_balance(
|
|
85
|
+
token_id="invalid-token",
|
|
86
|
+
wallet_address="0xWallet",
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
assert success is False
|
|
90
|
+
assert "NoneType" in error or "subscriptable" in error
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# BRAP Adapter
|
|
2
|
+
|
|
3
|
+
Adapter for cross-chain swaps and bridges via the BRAP (Bridge/Router/Adapter Protocol).
|
|
4
|
+
|
|
5
|
+
- **Type**: `BRAP`
|
|
6
|
+
- **Module**: `wayfinder_paths.adapters.brap_adapter.adapter.BRAPAdapter`
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
from wayfinder_paths.adapters.brap_adapter.adapter import BRAPAdapter
|
|
12
|
+
|
|
13
|
+
adapter = BRAPAdapter(strategy_wallet_signing_callback=signing_callback)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Methods
|
|
17
|
+
|
|
18
|
+
### best_quote
|
|
19
|
+
|
|
20
|
+
Get the best quote for a swap.
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
success, quote = await adapter.best_quote(
|
|
24
|
+
from_token_address="0x...",
|
|
25
|
+
to_token_address="0x...",
|
|
26
|
+
from_chain_id=8453,
|
|
27
|
+
to_chain_id=1,
|
|
28
|
+
from_address="0x...",
|
|
29
|
+
amount="1000000000",
|
|
30
|
+
preferred_providers=["enso"], # optional
|
|
31
|
+
)
|
|
32
|
+
if success:
|
|
33
|
+
print(f"Output: {quote.get('output_amount')}")
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### swap_from_token_ids
|
|
37
|
+
|
|
38
|
+
Execute a swap using token IDs.
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
success, result = await adapter.swap_from_token_ids(
|
|
42
|
+
from_token_id="usd-coin-base",
|
|
43
|
+
to_token_id="ethereum",
|
|
44
|
+
from_address="0x...",
|
|
45
|
+
amount="1000000000",
|
|
46
|
+
strategy_name="my_strategy",
|
|
47
|
+
preferred_providers=["enso"],
|
|
48
|
+
)
|
|
49
|
+
if success:
|
|
50
|
+
print(f"TX: {result.get('tx_hash')}")
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### swap_from_quote
|
|
54
|
+
|
|
55
|
+
Execute a swap from a pre-fetched quote.
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
success, result = await adapter.swap_from_quote(
|
|
59
|
+
from_token=from_token_info,
|
|
60
|
+
to_token=to_token_info,
|
|
61
|
+
from_address="0x...",
|
|
62
|
+
quote=quote,
|
|
63
|
+
strategy_name="my_strategy",
|
|
64
|
+
)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Testing
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
poetry run pytest wayfinder_paths/adapters/brap_adapter/ -v
|
|
71
|
+
```
|