wayfinder-paths 0.1.9__tar.gz → 0.1.10__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.9 → wayfinder_paths-0.1.10}/PKG-INFO +60 -187
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/README.md +59 -186
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/pyproject.toml +1 -1
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/CONFIG_GUIDE.md +1 -1
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/balance_adapter/README.md +1 -2
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/balance_adapter/adapter.py +4 -4
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/brap_adapter/adapter.py +139 -23
- wayfinder_paths-0.1.10/wayfinder_paths/adapters/moonwell_adapter/README.md +174 -0
- wayfinder_paths-0.1.10/wayfinder_paths/adapters/moonwell_adapter/__init__.py +7 -0
- wayfinder_paths-0.1.10/wayfinder_paths/adapters/moonwell_adapter/adapter.py +1226 -0
- wayfinder_paths-0.1.10/wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +635 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/clients/AuthClient.py +3 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/clients/WayfinderClient.py +2 -2
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/constants/__init__.py +0 -2
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/constants/base.py +6 -2
- wayfinder_paths-0.1.10/wayfinder_paths/core/constants/moonwell_abi.py +411 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/engine/StrategyJob.py +3 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/services/base.py +55 -0
- wayfinder_paths-0.1.10/wayfinder_paths/core/services/local_evm_txn.py +431 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/services/local_token_txn.py +46 -26
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/strategies/descriptors.py +1 -1
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/run_strategy.py +34 -74
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/scripts/create_strategy.py +2 -27
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/scripts/run_strategy.py +37 -7
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/basis_trading_strategy/strategy.py +1 -1
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md +0 -15
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +1 -1
- wayfinder_paths-0.1.10/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/README.md +108 -0
- wayfinder_paths-0.1.10/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/examples.json +11 -0
- wayfinder_paths-0.1.10/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +2975 -0
- wayfinder_paths-0.1.10/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +886 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +0 -7
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +1 -1
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/templates/adapter/README.md +5 -21
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/templates/adapter/adapter.py +1 -2
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/templates/adapter/test_adapter.py +1 -1
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/templates/strategy/README.md +4 -21
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/tests/test_smoke_manifest.py +17 -2
- wayfinder_paths-0.1.9/wayfinder_paths/adapters/balance_adapter/manifest.yaml +0 -8
- wayfinder_paths-0.1.9/wayfinder_paths/adapters/brap_adapter/manifest.yaml +0 -11
- wayfinder_paths-0.1.9/wayfinder_paths/adapters/hyperlend_adapter/manifest.yaml +0 -10
- wayfinder_paths-0.1.9/wayfinder_paths/adapters/hyperliquid_adapter/manifest.yaml +0 -8
- wayfinder_paths-0.1.9/wayfinder_paths/adapters/ledger_adapter/manifest.yaml +0 -11
- wayfinder_paths-0.1.9/wayfinder_paths/adapters/pool_adapter/manifest.yaml +0 -10
- wayfinder_paths-0.1.9/wayfinder_paths/adapters/token_adapter/manifest.yaml +0 -6
- wayfinder_paths-0.1.9/wayfinder_paths/core/engine/manifest.py +0 -97
- wayfinder_paths-0.1.9/wayfinder_paths/core/services/local_evm_txn.py +0 -351
- wayfinder_paths-0.1.9/wayfinder_paths/scripts/validate_manifests.py +0 -213
- wayfinder_paths-0.1.9/wayfinder_paths/strategies/basis_trading_strategy/manifest.yaml +0 -23
- wayfinder_paths-0.1.9/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/manifest.yaml +0 -7
- wayfinder_paths-0.1.9/wayfinder_paths/strategies/stablecoin_yield_strategy/manifest.yaml +0 -17
- wayfinder_paths-0.1.9/wayfinder_paths/templates/adapter/manifest.yaml +0 -6
- wayfinder_paths-0.1.9/wayfinder_paths/templates/strategy/manifest.yaml +0 -8
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/LICENSE +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/abis/generic/erc20.json +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/balance_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/balance_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/brap_adapter/README.md +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/brap_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/brap_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/brap_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/hyperlend_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/hyperlend_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/hyperliquid_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/hyperliquid_adapter/executor.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/hyperliquid_adapter/utils.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/ledger_adapter/README.md +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/ledger_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/ledger_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/ledger_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/ledger_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/pool_adapter/README.md +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/pool_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/pool_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/pool_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/pool_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/token_adapter/README.md +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/token_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/token_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/token_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/adapters/token_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/config.example.json +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/conftest.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/adapters/BaseAdapter.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/adapters/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/adapters/base.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/adapters/models.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/analytics/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/analytics/bootstrap.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/analytics/stats.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/analytics/test_analytics.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/clients/BRAPClient.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/clients/ClientManager.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/clients/HyperlendClient.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/clients/LedgerClient.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/clients/PoolClient.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/clients/TokenClient.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/clients/WalletClient.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/clients/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/clients/protocols.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/clients/sdk_example.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/config.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/constants/erc20_abi.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/constants/hyperlend_abi.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/engine/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/services/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/services/web3_service.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/settings.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/strategies/Strategy.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/strategies/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/strategies/base.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/utils/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/utils/evm_helpers.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/utils/wallets.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/wallets/README.md +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/wallets/WalletManager.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/core/wallets/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/policies/enso.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/policies/erc20.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/policies/evm.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/policies/hyper_evm.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/policies/hyperlend.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/policies/hyperliquid.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/policies/moonwell.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/policies/prjx.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/policies/util.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/scripts/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/scripts/make_wallets.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/basis_trading_strategy/README.md +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/basis_trading_strategy/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/basis_trading_strategy/constants.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/basis_trading_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/basis_trading_strategy/snapshot_mixin.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/basis_trading_strategy/types.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/config.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/stablecoin_yield_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/templates/adapter/examples.json +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/templates/strategy/examples.json +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/templates/strategy/strategy.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/templates/strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/tests/__init__.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/tests/test_test_coverage.py +0 -0
- {wayfinder_paths-0.1.9 → wayfinder_paths-0.1.10}/wayfinder_paths/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: wayfinder-paths
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.10
|
|
4
4
|
Summary: Wayfinder Path: strategies and adapters
|
|
5
5
|
Author: Wayfinder
|
|
6
6
|
Author-email: dev@wayfinder.ai
|
|
@@ -47,6 +47,9 @@ poetry install
|
|
|
47
47
|
just create-wallets
|
|
48
48
|
# Or manually: poetry run python wayfinder_paths/scripts/make_wallets.py -n 1
|
|
49
49
|
|
|
50
|
+
# To test a specific strategy
|
|
51
|
+
just just create-wallet stablecoin_yield_strategy
|
|
52
|
+
|
|
50
53
|
# Copy and configure
|
|
51
54
|
cp wayfinder_paths/config.example.json config.json
|
|
52
55
|
# Edit config.json with your Wayfinder credentials
|
|
@@ -72,7 +75,6 @@ wayfinder_paths/
|
|
|
72
75
|
│ ├── adapters/ # Your exchange/protocol integrations (community contributions)
|
|
73
76
|
│ │ ├── balance_adapter/
|
|
74
77
|
│ │ │ ├── adapter.py # Adapter implementation
|
|
75
|
-
│ │ │ ├── manifest.yaml # Adapter manifest (caps, entrypoint)
|
|
76
78
|
│ │ │ ├── examples.json # Example inputs for smoke
|
|
77
79
|
│ │ │ ├── README.md # Local notes
|
|
78
80
|
│ │ │ └── test_adapter.py # Local smoke test
|
|
@@ -81,7 +83,6 @@ wayfinder_paths/
|
|
|
81
83
|
│ ├── strategies/ # Your trading strategies (community contributions)
|
|
82
84
|
│ │ ├── stablecoin_yield_strategy/
|
|
83
85
|
│ │ │ ├── strategy.py # Strategy implementation
|
|
84
|
-
│ │ │ ├── manifest.yaml # Strategy manifest
|
|
85
86
|
│ │ │ ├── examples.json # Example inputs
|
|
86
87
|
│ │ │ ├── README.md # Local notes
|
|
87
88
|
│ │ │ └── test_strategy.py # Local smoke test
|
|
@@ -108,10 +109,9 @@ We welcome contributions! This is an open-source project where community members
|
|
|
108
109
|
3. **Copy a template** to get started:
|
|
109
110
|
- **For adapters**: Copy `wayfinder_paths/templates/adapter/` to `wayfinder_paths/adapters/my_adapter/`
|
|
110
111
|
- **For strategies**: Copy `wayfinder_paths/templates/strategy/` to `wayfinder_paths/strategies/my_strategy/`
|
|
111
|
-
4. **Customize** the template (rename classes,
|
|
112
|
+
4. **Customize** the template (rename classes, implement methods)
|
|
112
113
|
5. **Test your code** thoroughly using the provided test framework
|
|
113
|
-
6. **
|
|
114
|
-
7. **Submit a Pull Request** with a clear description of your changes
|
|
114
|
+
6. **Submit a Pull Request** with a clear description of your changes
|
|
115
115
|
|
|
116
116
|
### What You Can Contribute
|
|
117
117
|
|
|
@@ -125,29 +125,18 @@ We welcome contributions! This is an open-source project where community members
|
|
|
125
125
|
|
|
126
126
|
- **Start from the template**: Copy `wayfinder_paths/templates/adapter/` as a starting point
|
|
127
127
|
- Extend `BaseAdapter` from `wayfinder_paths/core/adapters/BaseAdapter.py`
|
|
128
|
-
-
|
|
129
|
-
- `entrypoint`: Full import path to your adapter class
|
|
130
|
-
- `capabilities`: List of capabilities your adapter provides
|
|
131
|
-
- `dependencies`: List of required client classes (e.g., `PoolClient`, `TokenClient`)
|
|
132
|
-
- Implement methods that fulfill the declared capabilities
|
|
128
|
+
- Implement your adapter methods
|
|
133
129
|
- Add comprehensive tests in `test_adapter.py`
|
|
134
130
|
- Include usage examples in `examples.json`
|
|
135
131
|
- Document your adapter in `README.md`
|
|
136
|
-
- Validate your manifest: `just validate-manifests`
|
|
137
132
|
|
|
138
133
|
#### For Strategies
|
|
139
134
|
|
|
140
135
|
- **Start from the template**: Use `just create-strategy "Strategy Name"` to create a new strategy with its own wallet, or copy `wayfinder_paths/templates/strategy/` manually
|
|
141
136
|
- Extend `Strategy` from `wayfinder_paths/core/strategies/Strategy.py`
|
|
142
|
-
- Create a `manifest.yaml` (template at `wayfinder_paths/templates/strategy/manifest.yaml`) with:
|
|
143
|
-
- `entrypoint`: Full import path to your strategy class
|
|
144
|
-
- `name`: Strategy directory name (used for wallet lookup)
|
|
145
|
-
- `permissions.policy`: Security policy for transaction permissions
|
|
146
|
-
- `adapters`: List of required adapters and their capabilities
|
|
147
137
|
- Implement required methods: `deposit()`, `update()`, `status()`, `withdraw()`
|
|
148
138
|
- Include test cases in `test_strategy.py`
|
|
149
139
|
- Add example configurations in `examples.json`
|
|
150
|
-
- Validate your manifest: `just validate-manifests`
|
|
151
140
|
|
|
152
141
|
#### General Guidelines
|
|
153
142
|
|
|
@@ -183,10 +172,7 @@ cp -r wayfinder_paths/templates/strategy wayfinder_paths/strategies/my_strategy
|
|
|
183
172
|
|
|
184
173
|
# 5. Customize the template (see template README.md files for details)
|
|
185
174
|
|
|
186
|
-
# 6.
|
|
187
|
-
just validate-manifests
|
|
188
|
-
|
|
189
|
-
# 7. Run tests
|
|
175
|
+
# 6. Run tests
|
|
190
176
|
poetry run pytest -k smoke -v
|
|
191
177
|
|
|
192
178
|
# Or test your specific contribution
|
|
@@ -211,7 +197,7 @@ The platform uses a unified client system for all API interactions. Clients are
|
|
|
211
197
|
### Clients vs Adapters
|
|
212
198
|
|
|
213
199
|
- **Clients**: Low-level, reusable service wrappers that talk to networks and external APIs. They handle auth, headers, retries, and response parsing, and expose generic capabilities (e.g., token info, tx building). Examples: `TokenClient`, `WalletClient`.
|
|
214
|
-
- **Adapters**: Strategy-facing integrations for a specific exchange/protocol. They compose one or more clients to implement a
|
|
200
|
+
- **Adapters**: Strategy-facing integrations for a specific exchange/protocol. They compose one or more clients to implement a set of capabilities (e.g., `supply`, `borrow`, `place_order`). Adapters encapsulate protocol-specific semantics and raise `NotImplementedError` for unsupported ops.
|
|
215
201
|
|
|
216
202
|
Recommended usage:
|
|
217
203
|
|
|
@@ -221,168 +207,6 @@ Recommended usage:
|
|
|
221
207
|
|
|
222
208
|
Data flow: `Strategy` → `Adapter` → `Client(s)` → network/API.
|
|
223
209
|
|
|
224
|
-
### Manifests
|
|
225
|
-
|
|
226
|
-
Every adapter and strategy requires a `manifest.yaml` file that declares its metadata, capabilities, and dependencies. Manifests are validated automatically in CI/CD and serve as the **single source of truth** for what each component can do.
|
|
227
|
-
|
|
228
|
-
#### Adapter Manifests
|
|
229
|
-
|
|
230
|
-
Adapter manifests declare the capabilities an adapter provides and the clients it depends on.
|
|
231
|
-
|
|
232
|
-
**Template:** Copy `wayfinder_paths/templates/adapter/manifest.yaml` as a starting point.
|
|
233
|
-
|
|
234
|
-
**Schema:**
|
|
235
|
-
|
|
236
|
-
```yaml
|
|
237
|
-
schema_version: "0.1"
|
|
238
|
-
entrypoint: "adapters.my_adapter.adapter.MyAdapter"
|
|
239
|
-
capabilities:
|
|
240
|
-
- "pool.read"
|
|
241
|
-
- "pool.analytics"
|
|
242
|
-
dependencies:
|
|
243
|
-
- "PoolClient"
|
|
244
|
-
- "TokenClient"
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
**Fields:**
|
|
248
|
-
|
|
249
|
-
- `schema_version`: Manifest schema version (currently `"0.1"`)
|
|
250
|
-
- `entrypoint`: Full Python import path to the adapter class (required)
|
|
251
|
-
- `capabilities`: List of abstract capabilities this adapter provides (required, non-empty)
|
|
252
|
-
- `dependencies`: List of client class names from `core.clients` that this adapter requires (required, non-empty)
|
|
253
|
-
|
|
254
|
-
**Example** (`wayfinder_paths/adapters/pool_adapter/manifest.yaml`):
|
|
255
|
-
|
|
256
|
-
```yaml
|
|
257
|
-
schema_version: "0.1"
|
|
258
|
-
entrypoint: "adapters.pool_adapter.adapter.PoolAdapter"
|
|
259
|
-
capabilities:
|
|
260
|
-
- "pool.read"
|
|
261
|
-
- "pool.analytics"
|
|
262
|
-
- "pool.discovery"
|
|
263
|
-
- "llama.data"
|
|
264
|
-
- "pool.reports"
|
|
265
|
-
dependencies:
|
|
266
|
-
- "PoolClient"
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
#### Strategy Manifests
|
|
270
|
-
|
|
271
|
-
Strategy manifests declare permissions and required adapters with their capabilities.
|
|
272
|
-
|
|
273
|
-
**Template:** Copy `wayfinder_paths/templates/strategy/manifest.yaml` as a starting point.
|
|
274
|
-
|
|
275
|
-
**Schema:**
|
|
276
|
-
|
|
277
|
-
```yaml
|
|
278
|
-
schema_version: "0.1"
|
|
279
|
-
entrypoint: "strategies.my_strategy.strategy.MyStrategy"
|
|
280
|
-
permissions:
|
|
281
|
-
policy: "(wallet.id == 'FORMAT_WALLET_ID') && (eth.tx.to == '0x...')"
|
|
282
|
-
adapters:
|
|
283
|
-
- name: "POOL"
|
|
284
|
-
capabilities: ["pool.read", "pool.analytics"]
|
|
285
|
-
- name: "BRAP"
|
|
286
|
-
capabilities: ["swap.quote", "swap.execute"]
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
**Fields:**
|
|
290
|
-
|
|
291
|
-
- `schema_version`: Manifest schema version (currently `"0.1"`)
|
|
292
|
-
- `entrypoint`: Full Python import path to the strategy class (required)
|
|
293
|
-
- `name`: Strategy directory name (optional, used for wallet lookup - defaults to directory name)
|
|
294
|
-
- `permissions.policy`: Security policy string that defines transaction permissions (required, non-empty)
|
|
295
|
-
- `adapters`: List of required adapters with their names and needed capabilities (required, non-empty)
|
|
296
|
-
- `name`: Adapter type identifier (e.g., "POOL", "BRAP")
|
|
297
|
-
- `capabilities`: List of capabilities required from this adapter
|
|
298
|
-
|
|
299
|
-
**Example** (`wayfinder_paths/strategies/stablecoin_yield_strategy/manifest.yaml`):
|
|
300
|
-
|
|
301
|
-
```yaml
|
|
302
|
-
schema_version: "0.1"
|
|
303
|
-
entrypoint: "strategies.stablecoin_yield_strategy.strategy.StablecoinYieldStrategy"
|
|
304
|
-
permissions:
|
|
305
|
-
policy: "(wallet.id == 'FORMAT_WALLET_ID') && ((eth.tx.data[0..10] == '0x095ea7b3' && eth.tx.data[34..74] == 'f75584ef6673ad213a685a1b58cc0330b8ea22cf') || (eth.tx.to == '0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf'))"
|
|
306
|
-
adapters:
|
|
307
|
-
- name: "BALANCE"
|
|
308
|
-
capabilities: ["wallet_read", "wallet_transfer"]
|
|
309
|
-
- name: "POOL"
|
|
310
|
-
capabilities: ["pool.read", "pool.analytics"]
|
|
311
|
-
- name: "BRAP"
|
|
312
|
-
capabilities: ["swap.quote", "swap.execute"]
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
#### Manifest Validation
|
|
316
|
-
|
|
317
|
-
Manifests are automatically validated to ensure:
|
|
318
|
-
|
|
319
|
-
- Schema compliance (all required fields present, correct types)
|
|
320
|
-
- Entrypoint classes exist and are importable
|
|
321
|
-
- Dependencies are valid client classes
|
|
322
|
-
- Permissions policies are non-empty
|
|
323
|
-
|
|
324
|
-
**Validate locally:**
|
|
325
|
-
|
|
326
|
-
```bash
|
|
327
|
-
# Validate all manifests
|
|
328
|
-
just validate-manifests
|
|
329
|
-
|
|
330
|
-
# Or manually
|
|
331
|
-
PYTHONPATH=wayfinder_paths poetry run python wayfinder_paths/scripts/validate_manifests.py
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
Validation runs automatically in CI/CD on every PR and push to main. All manifests must be valid before merging.
|
|
335
|
-
|
|
336
|
-
**How Validation Works:**
|
|
337
|
-
|
|
338
|
-
The `validate_manifests.py` script performs multi-stage validation:
|
|
339
|
-
|
|
340
|
-
1. **Schema Validation** (via Pydantic models):
|
|
341
|
-
- Loads YAML file and validates against `AdapterManifest` or `StrategyManifest` schema
|
|
342
|
-
- Checks required fields, types, and basic constraints (e.g., capabilities cannot be empty)
|
|
343
|
-
- Validates entrypoint format (must be full import path like `"adapters.pool_adapter.adapter.PoolAdapter"`)
|
|
344
|
-
|
|
345
|
-
2. **Entrypoint Verification**:
|
|
346
|
-
- **For Adapters**: Imports the entrypoint class and verifies it's a subclass of `BaseAdapter`
|
|
347
|
-
- **For Strategies**: Imports the entrypoint class and verifies it's a subclass of `Strategy`
|
|
348
|
-
- Uses Python's `__import__()` to dynamically import the module and class
|
|
349
|
-
- Catches import errors, missing classes, and type mismatches
|
|
350
|
-
|
|
351
|
-
3. **Dependency Verification** (adapters only):
|
|
352
|
-
- Validates that all declared dependencies (e.g., `PoolClient`, `TokenClient`) exist in `core.clients`
|
|
353
|
-
- Attempts to import each dependency as `core.clients.{DepName}`
|
|
354
|
-
|
|
355
|
-
4. **Permissions Validation** (strategies only):
|
|
356
|
-
- Validated by Pydantic: ensures `permissions.policy` exists and is non-empty
|
|
357
|
-
- Policy syntax is not parsed/validated (assumed to be valid at runtime)
|
|
358
|
-
|
|
359
|
-
**Validation Flow:**
|
|
360
|
-
|
|
361
|
-
```
|
|
362
|
-
For each manifest file:
|
|
363
|
-
1. Load YAML → Parse with Pydantic (schema validation)
|
|
364
|
-
2. Import entrypoint class → Verify inheritance (entrypoint validation)
|
|
365
|
-
3. For adapters: Import dependencies → Verify they exist (dependency validation)
|
|
366
|
-
4. Collect all errors → Report results
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
The script automatically discovers all manifests by scanning:
|
|
370
|
-
|
|
371
|
-
- `wayfinder_paths/adapters/*/manifest.yaml` for adapter manifests
|
|
372
|
-
- `wayfinder_paths/strategies/*/manifest.yaml` for strategy manifests
|
|
373
|
-
|
|
374
|
-
All errors are collected and reported at the end, with the script exiting with code 1 if any validation fails.
|
|
375
|
-
|
|
376
|
-
#### Capabilities
|
|
377
|
-
|
|
378
|
-
Capabilities are abstract operation identifiers (e.g., `"pool.read"`, `"swap.execute"`) declared in manifests. They represent what operations an adapter can perform, not specific method names. The manifest is the **single source of truth** for capabilities—they are not duplicated in code.
|
|
379
|
-
|
|
380
|
-
When creating an adapter:
|
|
381
|
-
|
|
382
|
-
1. Declare capabilities in your `manifest.yaml`
|
|
383
|
-
2. Implement methods that fulfill those capabilities
|
|
384
|
-
3. Capabilities are validated at manifest validation time (entrypoint must be importable)
|
|
385
|
-
|
|
386
210
|
### Configuration
|
|
387
211
|
|
|
388
212
|
Configuration is split between:
|
|
@@ -473,7 +297,7 @@ class MyAdapter(BaseAdapter):
|
|
|
473
297
|
self.pool_client = PoolClient()
|
|
474
298
|
|
|
475
299
|
async def connect(self) -> bool:
|
|
476
|
-
"""No-op for read-only adapters, but kept for
|
|
300
|
+
"""No-op for read-only adapters, but kept for interface consistency."""
|
|
477
301
|
return True
|
|
478
302
|
|
|
479
303
|
async def get_pools(self, pool_ids: list[str]):
|
|
@@ -546,6 +370,54 @@ class MyStrategy(Strategy):
|
|
|
546
370
|
}
|
|
547
371
|
```
|
|
548
372
|
|
|
373
|
+
### Built-in Strategies
|
|
374
|
+
|
|
375
|
+
The following strategies are available and can be run using the CLI:
|
|
376
|
+
|
|
377
|
+
| Strategy | Description | Chain |
|
|
378
|
+
|----------|-------------|-------|
|
|
379
|
+
| `basis_trading_strategy` | Delta-neutral basis trading | - |
|
|
380
|
+
| `hyperlend_stable_yield_strategy` | Stable yield on HyperLend | HyperEVM |
|
|
381
|
+
| `moonwell_wsteth_loop_strategy` | Leveraged wstETH yield loop | Base |
|
|
382
|
+
|
|
383
|
+
#### Running Strategies
|
|
384
|
+
|
|
385
|
+
```bash
|
|
386
|
+
# Check strategy status
|
|
387
|
+
poetry run python wayfinder_paths/scripts/run_strategy.py \
|
|
388
|
+
--strategy moonwell_wsteth_loop_strategy \
|
|
389
|
+
--main-wallet-label main \
|
|
390
|
+
--strategy-wallet-label moonwell_wsteth_loop_strategy \
|
|
391
|
+
status
|
|
392
|
+
|
|
393
|
+
# Deposit funds (USDC amount, optional ETH for gas)
|
|
394
|
+
poetry run python wayfinder_paths/scripts/run_strategy.py \
|
|
395
|
+
--strategy moonwell_wsteth_loop_strategy \
|
|
396
|
+
--main-wallet-label main \
|
|
397
|
+
--strategy-wallet-label moonwell_wsteth_loop_strategy \
|
|
398
|
+
deposit --usdc 100 --eth 0.01
|
|
399
|
+
|
|
400
|
+
# Run periodic update
|
|
401
|
+
poetry run python wayfinder_paths/scripts/run_strategy.py \
|
|
402
|
+
--strategy moonwell_wsteth_loop_strategy \
|
|
403
|
+
--main-wallet-label main \
|
|
404
|
+
--strategy-wallet-label moonwell_wsteth_loop_strategy \
|
|
405
|
+
update
|
|
406
|
+
|
|
407
|
+
# Withdraw funds (omit --amount for full withdrawal)
|
|
408
|
+
poetry run python wayfinder_paths/scripts/run_strategy.py \
|
|
409
|
+
--strategy moonwell_wsteth_loop_strategy \
|
|
410
|
+
--main-wallet-label main \
|
|
411
|
+
--strategy-wallet-label moonwell_wsteth_loop_strategy \
|
|
412
|
+
withdraw --amount 50
|
|
413
|
+
|
|
414
|
+
# Run in simulation mode (no real transactions)
|
|
415
|
+
poetry run python wayfinder_paths/scripts/run_strategy.py \
|
|
416
|
+
--strategy moonwell_wsteth_loop_strategy \
|
|
417
|
+
--simulation \
|
|
418
|
+
status
|
|
419
|
+
```
|
|
420
|
+
|
|
549
421
|
### Built-in adapters
|
|
550
422
|
|
|
551
423
|
- **BALANCE (BalanceAdapter)**: wraps `WalletClient`/`TokenClient` to read wallet, token, and pool balances and now orchestrates transfers between the main/strategy wallets with ledger bookkeeping. Requires a `Web3Service` so it can share the same wallet provider as the strategy.
|
|
@@ -554,8 +426,9 @@ class MyStrategy(Strategy):
|
|
|
554
426
|
- **LEDGER (LedgerAdapter)**: records deposits, withdrawals, custom operations, and cashflows via `LedgerClient`, and can read strategy transaction summaries.
|
|
555
427
|
- **TOKEN (TokenAdapter)**: lightweight wrapper around `TokenClient` for token metadata, live price snapshots, and gas token lookups.
|
|
556
428
|
- **HYPERLEND (HyperlendAdapter)**: connects to `HyperlendClient` for lending/supply caps inside the HyperLend strategy.
|
|
429
|
+
- **MOONWELL (MoonwellAdapter)**: interfaces with Moonwell protocol on Base for lending, borrowing, collateral management, and WELL rewards.
|
|
557
430
|
|
|
558
|
-
|
|
431
|
+
Strategies register the adapters they need in their `__init__` method. Adapters implement their specific capabilities and raise `NotImplementedError` for unsupported operations.
|
|
559
432
|
|
|
560
433
|
## 🧪 Testing
|
|
561
434
|
|
|
@@ -24,6 +24,9 @@ poetry install
|
|
|
24
24
|
just create-wallets
|
|
25
25
|
# Or manually: poetry run python wayfinder_paths/scripts/make_wallets.py -n 1
|
|
26
26
|
|
|
27
|
+
# To test a specific strategy
|
|
28
|
+
just just create-wallet stablecoin_yield_strategy
|
|
29
|
+
|
|
27
30
|
# Copy and configure
|
|
28
31
|
cp wayfinder_paths/config.example.json config.json
|
|
29
32
|
# Edit config.json with your Wayfinder credentials
|
|
@@ -49,7 +52,6 @@ wayfinder_paths/
|
|
|
49
52
|
│ ├── adapters/ # Your exchange/protocol integrations (community contributions)
|
|
50
53
|
│ │ ├── balance_adapter/
|
|
51
54
|
│ │ │ ├── adapter.py # Adapter implementation
|
|
52
|
-
│ │ │ ├── manifest.yaml # Adapter manifest (caps, entrypoint)
|
|
53
55
|
│ │ │ ├── examples.json # Example inputs for smoke
|
|
54
56
|
│ │ │ ├── README.md # Local notes
|
|
55
57
|
│ │ │ └── test_adapter.py # Local smoke test
|
|
@@ -58,7 +60,6 @@ wayfinder_paths/
|
|
|
58
60
|
│ ├── strategies/ # Your trading strategies (community contributions)
|
|
59
61
|
│ │ ├── stablecoin_yield_strategy/
|
|
60
62
|
│ │ │ ├── strategy.py # Strategy implementation
|
|
61
|
-
│ │ │ ├── manifest.yaml # Strategy manifest
|
|
62
63
|
│ │ │ ├── examples.json # Example inputs
|
|
63
64
|
│ │ │ ├── README.md # Local notes
|
|
64
65
|
│ │ │ └── test_strategy.py # Local smoke test
|
|
@@ -85,10 +86,9 @@ We welcome contributions! This is an open-source project where community members
|
|
|
85
86
|
3. **Copy a template** to get started:
|
|
86
87
|
- **For adapters**: Copy `wayfinder_paths/templates/adapter/` to `wayfinder_paths/adapters/my_adapter/`
|
|
87
88
|
- **For strategies**: Copy `wayfinder_paths/templates/strategy/` to `wayfinder_paths/strategies/my_strategy/`
|
|
88
|
-
4. **Customize** the template (rename classes,
|
|
89
|
+
4. **Customize** the template (rename classes, implement methods)
|
|
89
90
|
5. **Test your code** thoroughly using the provided test framework
|
|
90
|
-
6. **
|
|
91
|
-
7. **Submit a Pull Request** with a clear description of your changes
|
|
91
|
+
6. **Submit a Pull Request** with a clear description of your changes
|
|
92
92
|
|
|
93
93
|
### What You Can Contribute
|
|
94
94
|
|
|
@@ -102,29 +102,18 @@ We welcome contributions! This is an open-source project where community members
|
|
|
102
102
|
|
|
103
103
|
- **Start from the template**: Copy `wayfinder_paths/templates/adapter/` as a starting point
|
|
104
104
|
- Extend `BaseAdapter` from `wayfinder_paths/core/adapters/BaseAdapter.py`
|
|
105
|
-
-
|
|
106
|
-
- `entrypoint`: Full import path to your adapter class
|
|
107
|
-
- `capabilities`: List of capabilities your adapter provides
|
|
108
|
-
- `dependencies`: List of required client classes (e.g., `PoolClient`, `TokenClient`)
|
|
109
|
-
- Implement methods that fulfill the declared capabilities
|
|
105
|
+
- Implement your adapter methods
|
|
110
106
|
- Add comprehensive tests in `test_adapter.py`
|
|
111
107
|
- Include usage examples in `examples.json`
|
|
112
108
|
- Document your adapter in `README.md`
|
|
113
|
-
- Validate your manifest: `just validate-manifests`
|
|
114
109
|
|
|
115
110
|
#### For Strategies
|
|
116
111
|
|
|
117
112
|
- **Start from the template**: Use `just create-strategy "Strategy Name"` to create a new strategy with its own wallet, or copy `wayfinder_paths/templates/strategy/` manually
|
|
118
113
|
- Extend `Strategy` from `wayfinder_paths/core/strategies/Strategy.py`
|
|
119
|
-
- Create a `manifest.yaml` (template at `wayfinder_paths/templates/strategy/manifest.yaml`) with:
|
|
120
|
-
- `entrypoint`: Full import path to your strategy class
|
|
121
|
-
- `name`: Strategy directory name (used for wallet lookup)
|
|
122
|
-
- `permissions.policy`: Security policy for transaction permissions
|
|
123
|
-
- `adapters`: List of required adapters and their capabilities
|
|
124
114
|
- Implement required methods: `deposit()`, `update()`, `status()`, `withdraw()`
|
|
125
115
|
- Include test cases in `test_strategy.py`
|
|
126
116
|
- Add example configurations in `examples.json`
|
|
127
|
-
- Validate your manifest: `just validate-manifests`
|
|
128
117
|
|
|
129
118
|
#### General Guidelines
|
|
130
119
|
|
|
@@ -160,10 +149,7 @@ cp -r wayfinder_paths/templates/strategy wayfinder_paths/strategies/my_strategy
|
|
|
160
149
|
|
|
161
150
|
# 5. Customize the template (see template README.md files for details)
|
|
162
151
|
|
|
163
|
-
# 6.
|
|
164
|
-
just validate-manifests
|
|
165
|
-
|
|
166
|
-
# 7. Run tests
|
|
152
|
+
# 6. Run tests
|
|
167
153
|
poetry run pytest -k smoke -v
|
|
168
154
|
|
|
169
155
|
# Or test your specific contribution
|
|
@@ -188,7 +174,7 @@ The platform uses a unified client system for all API interactions. Clients are
|
|
|
188
174
|
### Clients vs Adapters
|
|
189
175
|
|
|
190
176
|
- **Clients**: Low-level, reusable service wrappers that talk to networks and external APIs. They handle auth, headers, retries, and response parsing, and expose generic capabilities (e.g., token info, tx building). Examples: `TokenClient`, `WalletClient`.
|
|
191
|
-
- **Adapters**: Strategy-facing integrations for a specific exchange/protocol. They compose one or more clients to implement a
|
|
177
|
+
- **Adapters**: Strategy-facing integrations for a specific exchange/protocol. They compose one or more clients to implement a set of capabilities (e.g., `supply`, `borrow`, `place_order`). Adapters encapsulate protocol-specific semantics and raise `NotImplementedError` for unsupported ops.
|
|
192
178
|
|
|
193
179
|
Recommended usage:
|
|
194
180
|
|
|
@@ -198,168 +184,6 @@ Recommended usage:
|
|
|
198
184
|
|
|
199
185
|
Data flow: `Strategy` → `Adapter` → `Client(s)` → network/API.
|
|
200
186
|
|
|
201
|
-
### Manifests
|
|
202
|
-
|
|
203
|
-
Every adapter and strategy requires a `manifest.yaml` file that declares its metadata, capabilities, and dependencies. Manifests are validated automatically in CI/CD and serve as the **single source of truth** for what each component can do.
|
|
204
|
-
|
|
205
|
-
#### Adapter Manifests
|
|
206
|
-
|
|
207
|
-
Adapter manifests declare the capabilities an adapter provides and the clients it depends on.
|
|
208
|
-
|
|
209
|
-
**Template:** Copy `wayfinder_paths/templates/adapter/manifest.yaml` as a starting point.
|
|
210
|
-
|
|
211
|
-
**Schema:**
|
|
212
|
-
|
|
213
|
-
```yaml
|
|
214
|
-
schema_version: "0.1"
|
|
215
|
-
entrypoint: "adapters.my_adapter.adapter.MyAdapter"
|
|
216
|
-
capabilities:
|
|
217
|
-
- "pool.read"
|
|
218
|
-
- "pool.analytics"
|
|
219
|
-
dependencies:
|
|
220
|
-
- "PoolClient"
|
|
221
|
-
- "TokenClient"
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
**Fields:**
|
|
225
|
-
|
|
226
|
-
- `schema_version`: Manifest schema version (currently `"0.1"`)
|
|
227
|
-
- `entrypoint`: Full Python import path to the adapter class (required)
|
|
228
|
-
- `capabilities`: List of abstract capabilities this adapter provides (required, non-empty)
|
|
229
|
-
- `dependencies`: List of client class names from `core.clients` that this adapter requires (required, non-empty)
|
|
230
|
-
|
|
231
|
-
**Example** (`wayfinder_paths/adapters/pool_adapter/manifest.yaml`):
|
|
232
|
-
|
|
233
|
-
```yaml
|
|
234
|
-
schema_version: "0.1"
|
|
235
|
-
entrypoint: "adapters.pool_adapter.adapter.PoolAdapter"
|
|
236
|
-
capabilities:
|
|
237
|
-
- "pool.read"
|
|
238
|
-
- "pool.analytics"
|
|
239
|
-
- "pool.discovery"
|
|
240
|
-
- "llama.data"
|
|
241
|
-
- "pool.reports"
|
|
242
|
-
dependencies:
|
|
243
|
-
- "PoolClient"
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
#### Strategy Manifests
|
|
247
|
-
|
|
248
|
-
Strategy manifests declare permissions and required adapters with their capabilities.
|
|
249
|
-
|
|
250
|
-
**Template:** Copy `wayfinder_paths/templates/strategy/manifest.yaml` as a starting point.
|
|
251
|
-
|
|
252
|
-
**Schema:**
|
|
253
|
-
|
|
254
|
-
```yaml
|
|
255
|
-
schema_version: "0.1"
|
|
256
|
-
entrypoint: "strategies.my_strategy.strategy.MyStrategy"
|
|
257
|
-
permissions:
|
|
258
|
-
policy: "(wallet.id == 'FORMAT_WALLET_ID') && (eth.tx.to == '0x...')"
|
|
259
|
-
adapters:
|
|
260
|
-
- name: "POOL"
|
|
261
|
-
capabilities: ["pool.read", "pool.analytics"]
|
|
262
|
-
- name: "BRAP"
|
|
263
|
-
capabilities: ["swap.quote", "swap.execute"]
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
**Fields:**
|
|
267
|
-
|
|
268
|
-
- `schema_version`: Manifest schema version (currently `"0.1"`)
|
|
269
|
-
- `entrypoint`: Full Python import path to the strategy class (required)
|
|
270
|
-
- `name`: Strategy directory name (optional, used for wallet lookup - defaults to directory name)
|
|
271
|
-
- `permissions.policy`: Security policy string that defines transaction permissions (required, non-empty)
|
|
272
|
-
- `adapters`: List of required adapters with their names and needed capabilities (required, non-empty)
|
|
273
|
-
- `name`: Adapter type identifier (e.g., "POOL", "BRAP")
|
|
274
|
-
- `capabilities`: List of capabilities required from this adapter
|
|
275
|
-
|
|
276
|
-
**Example** (`wayfinder_paths/strategies/stablecoin_yield_strategy/manifest.yaml`):
|
|
277
|
-
|
|
278
|
-
```yaml
|
|
279
|
-
schema_version: "0.1"
|
|
280
|
-
entrypoint: "strategies.stablecoin_yield_strategy.strategy.StablecoinYieldStrategy"
|
|
281
|
-
permissions:
|
|
282
|
-
policy: "(wallet.id == 'FORMAT_WALLET_ID') && ((eth.tx.data[0..10] == '0x095ea7b3' && eth.tx.data[34..74] == 'f75584ef6673ad213a685a1b58cc0330b8ea22cf') || (eth.tx.to == '0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf'))"
|
|
283
|
-
adapters:
|
|
284
|
-
- name: "BALANCE"
|
|
285
|
-
capabilities: ["wallet_read", "wallet_transfer"]
|
|
286
|
-
- name: "POOL"
|
|
287
|
-
capabilities: ["pool.read", "pool.analytics"]
|
|
288
|
-
- name: "BRAP"
|
|
289
|
-
capabilities: ["swap.quote", "swap.execute"]
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
#### Manifest Validation
|
|
293
|
-
|
|
294
|
-
Manifests are automatically validated to ensure:
|
|
295
|
-
|
|
296
|
-
- Schema compliance (all required fields present, correct types)
|
|
297
|
-
- Entrypoint classes exist and are importable
|
|
298
|
-
- Dependencies are valid client classes
|
|
299
|
-
- Permissions policies are non-empty
|
|
300
|
-
|
|
301
|
-
**Validate locally:**
|
|
302
|
-
|
|
303
|
-
```bash
|
|
304
|
-
# Validate all manifests
|
|
305
|
-
just validate-manifests
|
|
306
|
-
|
|
307
|
-
# Or manually
|
|
308
|
-
PYTHONPATH=wayfinder_paths poetry run python wayfinder_paths/scripts/validate_manifests.py
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
Validation runs automatically in CI/CD on every PR and push to main. All manifests must be valid before merging.
|
|
312
|
-
|
|
313
|
-
**How Validation Works:**
|
|
314
|
-
|
|
315
|
-
The `validate_manifests.py` script performs multi-stage validation:
|
|
316
|
-
|
|
317
|
-
1. **Schema Validation** (via Pydantic models):
|
|
318
|
-
- Loads YAML file and validates against `AdapterManifest` or `StrategyManifest` schema
|
|
319
|
-
- Checks required fields, types, and basic constraints (e.g., capabilities cannot be empty)
|
|
320
|
-
- Validates entrypoint format (must be full import path like `"adapters.pool_adapter.adapter.PoolAdapter"`)
|
|
321
|
-
|
|
322
|
-
2. **Entrypoint Verification**:
|
|
323
|
-
- **For Adapters**: Imports the entrypoint class and verifies it's a subclass of `BaseAdapter`
|
|
324
|
-
- **For Strategies**: Imports the entrypoint class and verifies it's a subclass of `Strategy`
|
|
325
|
-
- Uses Python's `__import__()` to dynamically import the module and class
|
|
326
|
-
- Catches import errors, missing classes, and type mismatches
|
|
327
|
-
|
|
328
|
-
3. **Dependency Verification** (adapters only):
|
|
329
|
-
- Validates that all declared dependencies (e.g., `PoolClient`, `TokenClient`) exist in `core.clients`
|
|
330
|
-
- Attempts to import each dependency as `core.clients.{DepName}`
|
|
331
|
-
|
|
332
|
-
4. **Permissions Validation** (strategies only):
|
|
333
|
-
- Validated by Pydantic: ensures `permissions.policy` exists and is non-empty
|
|
334
|
-
- Policy syntax is not parsed/validated (assumed to be valid at runtime)
|
|
335
|
-
|
|
336
|
-
**Validation Flow:**
|
|
337
|
-
|
|
338
|
-
```
|
|
339
|
-
For each manifest file:
|
|
340
|
-
1. Load YAML → Parse with Pydantic (schema validation)
|
|
341
|
-
2. Import entrypoint class → Verify inheritance (entrypoint validation)
|
|
342
|
-
3. For adapters: Import dependencies → Verify they exist (dependency validation)
|
|
343
|
-
4. Collect all errors → Report results
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
The script automatically discovers all manifests by scanning:
|
|
347
|
-
|
|
348
|
-
- `wayfinder_paths/adapters/*/manifest.yaml` for adapter manifests
|
|
349
|
-
- `wayfinder_paths/strategies/*/manifest.yaml` for strategy manifests
|
|
350
|
-
|
|
351
|
-
All errors are collected and reported at the end, with the script exiting with code 1 if any validation fails.
|
|
352
|
-
|
|
353
|
-
#### Capabilities
|
|
354
|
-
|
|
355
|
-
Capabilities are abstract operation identifiers (e.g., `"pool.read"`, `"swap.execute"`) declared in manifests. They represent what operations an adapter can perform, not specific method names. The manifest is the **single source of truth** for capabilities—they are not duplicated in code.
|
|
356
|
-
|
|
357
|
-
When creating an adapter:
|
|
358
|
-
|
|
359
|
-
1. Declare capabilities in your `manifest.yaml`
|
|
360
|
-
2. Implement methods that fulfill those capabilities
|
|
361
|
-
3. Capabilities are validated at manifest validation time (entrypoint must be importable)
|
|
362
|
-
|
|
363
187
|
### Configuration
|
|
364
188
|
|
|
365
189
|
Configuration is split between:
|
|
@@ -450,7 +274,7 @@ class MyAdapter(BaseAdapter):
|
|
|
450
274
|
self.pool_client = PoolClient()
|
|
451
275
|
|
|
452
276
|
async def connect(self) -> bool:
|
|
453
|
-
"""No-op for read-only adapters, but kept for
|
|
277
|
+
"""No-op for read-only adapters, but kept for interface consistency."""
|
|
454
278
|
return True
|
|
455
279
|
|
|
456
280
|
async def get_pools(self, pool_ids: list[str]):
|
|
@@ -523,6 +347,54 @@ class MyStrategy(Strategy):
|
|
|
523
347
|
}
|
|
524
348
|
```
|
|
525
349
|
|
|
350
|
+
### Built-in Strategies
|
|
351
|
+
|
|
352
|
+
The following strategies are available and can be run using the CLI:
|
|
353
|
+
|
|
354
|
+
| Strategy | Description | Chain |
|
|
355
|
+
|----------|-------------|-------|
|
|
356
|
+
| `basis_trading_strategy` | Delta-neutral basis trading | - |
|
|
357
|
+
| `hyperlend_stable_yield_strategy` | Stable yield on HyperLend | HyperEVM |
|
|
358
|
+
| `moonwell_wsteth_loop_strategy` | Leveraged wstETH yield loop | Base |
|
|
359
|
+
|
|
360
|
+
#### Running Strategies
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
# Check strategy status
|
|
364
|
+
poetry run python wayfinder_paths/scripts/run_strategy.py \
|
|
365
|
+
--strategy moonwell_wsteth_loop_strategy \
|
|
366
|
+
--main-wallet-label main \
|
|
367
|
+
--strategy-wallet-label moonwell_wsteth_loop_strategy \
|
|
368
|
+
status
|
|
369
|
+
|
|
370
|
+
# Deposit funds (USDC amount, optional ETH for gas)
|
|
371
|
+
poetry run python wayfinder_paths/scripts/run_strategy.py \
|
|
372
|
+
--strategy moonwell_wsteth_loop_strategy \
|
|
373
|
+
--main-wallet-label main \
|
|
374
|
+
--strategy-wallet-label moonwell_wsteth_loop_strategy \
|
|
375
|
+
deposit --usdc 100 --eth 0.01
|
|
376
|
+
|
|
377
|
+
# Run periodic update
|
|
378
|
+
poetry run python wayfinder_paths/scripts/run_strategy.py \
|
|
379
|
+
--strategy moonwell_wsteth_loop_strategy \
|
|
380
|
+
--main-wallet-label main \
|
|
381
|
+
--strategy-wallet-label moonwell_wsteth_loop_strategy \
|
|
382
|
+
update
|
|
383
|
+
|
|
384
|
+
# Withdraw funds (omit --amount for full withdrawal)
|
|
385
|
+
poetry run python wayfinder_paths/scripts/run_strategy.py \
|
|
386
|
+
--strategy moonwell_wsteth_loop_strategy \
|
|
387
|
+
--main-wallet-label main \
|
|
388
|
+
--strategy-wallet-label moonwell_wsteth_loop_strategy \
|
|
389
|
+
withdraw --amount 50
|
|
390
|
+
|
|
391
|
+
# Run in simulation mode (no real transactions)
|
|
392
|
+
poetry run python wayfinder_paths/scripts/run_strategy.py \
|
|
393
|
+
--strategy moonwell_wsteth_loop_strategy \
|
|
394
|
+
--simulation \
|
|
395
|
+
status
|
|
396
|
+
```
|
|
397
|
+
|
|
526
398
|
### Built-in adapters
|
|
527
399
|
|
|
528
400
|
- **BALANCE (BalanceAdapter)**: wraps `WalletClient`/`TokenClient` to read wallet, token, and pool balances and now orchestrates transfers between the main/strategy wallets with ledger bookkeeping. Requires a `Web3Service` so it can share the same wallet provider as the strategy.
|
|
@@ -531,8 +403,9 @@ class MyStrategy(Strategy):
|
|
|
531
403
|
- **LEDGER (LedgerAdapter)**: records deposits, withdrawals, custom operations, and cashflows via `LedgerClient`, and can read strategy transaction summaries.
|
|
532
404
|
- **TOKEN (TokenAdapter)**: lightweight wrapper around `TokenClient` for token metadata, live price snapshots, and gas token lookups.
|
|
533
405
|
- **HYPERLEND (HyperlendAdapter)**: connects to `HyperlendClient` for lending/supply caps inside the HyperLend strategy.
|
|
406
|
+
- **MOONWELL (MoonwellAdapter)**: interfaces with Moonwell protocol on Base for lending, borrowing, collateral management, and WELL rewards.
|
|
534
407
|
|
|
535
|
-
|
|
408
|
+
Strategies register the adapters they need in their `__init__` method. Adapters implement their specific capabilities and raise `NotImplementedError` for unsupported operations.
|
|
536
409
|
|
|
537
410
|
## 🧪 Testing
|
|
538
411
|
|