wayfinder-paths 0.1.22__py3-none-any.whl → 0.1.24__py3-none-any.whl
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/__init__.py +0 -4
- wayfinder_paths/adapters/balance_adapter/README.md +0 -1
- wayfinder_paths/adapters/balance_adapter/adapter.py +313 -167
- wayfinder_paths/adapters/balance_adapter/manifest.yaml +8 -0
- wayfinder_paths/adapters/balance_adapter/test_adapter.py +41 -124
- wayfinder_paths/adapters/boros_adapter/__init__.py +17 -0
- wayfinder_paths/adapters/boros_adapter/adapter.py +1574 -0
- wayfinder_paths/adapters/boros_adapter/client.py +476 -0
- wayfinder_paths/adapters/boros_adapter/manifest.yaml +10 -0
- wayfinder_paths/adapters/boros_adapter/parsers.py +88 -0
- wayfinder_paths/adapters/boros_adapter/test_adapter.py +460 -0
- wayfinder_paths/adapters/boros_adapter/test_golden.py +156 -0
- wayfinder_paths/adapters/boros_adapter/types.py +70 -0
- wayfinder_paths/adapters/boros_adapter/utils.py +85 -0
- wayfinder_paths/adapters/brap_adapter/README.md +22 -75
- wayfinder_paths/adapters/brap_adapter/adapter.py +187 -576
- wayfinder_paths/adapters/brap_adapter/examples.json +21 -140
- wayfinder_paths/adapters/brap_adapter/manifest.yaml +9 -0
- wayfinder_paths/adapters/brap_adapter/test_adapter.py +6 -234
- wayfinder_paths/adapters/hyperlend_adapter/adapter.py +180 -92
- wayfinder_paths/adapters/hyperlend_adapter/manifest.yaml +9 -0
- wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +82 -14
- wayfinder_paths/adapters/hyperliquid_adapter/__init__.py +2 -9
- wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +586 -61
- wayfinder_paths/adapters/hyperliquid_adapter/executor.py +47 -68
- wayfinder_paths/adapters/hyperliquid_adapter/manifest.yaml +14 -0
- wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +2 -3
- wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +17 -21
- wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +3 -6
- wayfinder_paths/adapters/hyperliquid_adapter/test_executor.py +4 -8
- wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +2 -2
- wayfinder_paths/adapters/ledger_adapter/README.md +4 -1
- wayfinder_paths/adapters/ledger_adapter/adapter.py +3 -3
- wayfinder_paths/adapters/ledger_adapter/manifest.yaml +7 -0
- wayfinder_paths/adapters/ledger_adapter/test_adapter.py +1 -2
- wayfinder_paths/adapters/moonwell_adapter/adapter.py +649 -547
- wayfinder_paths/adapters/moonwell_adapter/manifest.yaml +14 -0
- wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +160 -239
- wayfinder_paths/adapters/multicall_adapter/__init__.py +7 -0
- wayfinder_paths/adapters/multicall_adapter/adapter.py +166 -0
- wayfinder_paths/adapters/multicall_adapter/manifest.yaml +5 -0
- wayfinder_paths/adapters/multicall_adapter/test_adapter.py +97 -0
- wayfinder_paths/adapters/pendle_adapter/README.md +102 -0
- wayfinder_paths/adapters/pendle_adapter/__init__.py +7 -0
- wayfinder_paths/adapters/pendle_adapter/adapter.py +1992 -0
- wayfinder_paths/adapters/pendle_adapter/examples.json +11 -0
- wayfinder_paths/adapters/pendle_adapter/manifest.yaml +21 -0
- wayfinder_paths/adapters/pendle_adapter/test_adapter.py +666 -0
- wayfinder_paths/adapters/pool_adapter/manifest.yaml +6 -0
- wayfinder_paths/adapters/token_adapter/adapter.py +14 -0
- wayfinder_paths/adapters/token_adapter/examples.json +0 -4
- wayfinder_paths/adapters/token_adapter/manifest.yaml +7 -0
- wayfinder_paths/conftest.py +24 -17
- wayfinder_paths/core/__init__.py +0 -3
- wayfinder_paths/core/adapters/BaseAdapter.py +0 -25
- wayfinder_paths/core/adapters/models.py +17 -7
- wayfinder_paths/core/clients/BRAPClient.py +4 -1
- wayfinder_paths/core/clients/ClientManager.py +0 -7
- wayfinder_paths/core/clients/LedgerClient.py +196 -172
- wayfinder_paths/core/clients/TokenClient.py +47 -1
- wayfinder_paths/core/clients/WayfinderClient.py +1 -3
- wayfinder_paths/core/clients/__init__.py +0 -5
- wayfinder_paths/core/clients/protocols.py +21 -35
- wayfinder_paths/core/clients/test_ledger_client.py +448 -0
- wayfinder_paths/core/config.py +10 -162
- wayfinder_paths/core/constants/__init__.py +73 -2
- wayfinder_paths/core/constants/base.py +8 -17
- wayfinder_paths/core/constants/chains.py +36 -0
- wayfinder_paths/core/constants/contracts.py +52 -0
- wayfinder_paths/core/constants/erc20_abi.py +0 -1
- wayfinder_paths/core/constants/hyperlend_abi.py +0 -4
- wayfinder_paths/core/constants/hyperliquid.py +16 -0
- wayfinder_paths/core/constants/moonwell_abi.py +0 -15
- wayfinder_paths/core/constants/tokens.py +9 -0
- wayfinder_paths/core/engine/manifest.py +66 -0
- wayfinder_paths/core/strategies/Strategy.py +0 -71
- wayfinder_paths/core/strategies/__init__.py +10 -1
- wayfinder_paths/core/strategies/opa_loop.py +167 -0
- wayfinder_paths/core/utils/evm_helpers.py +5 -15
- wayfinder_paths/core/utils/test_transaction.py +289 -0
- wayfinder_paths/core/utils/tokens.py +28 -0
- wayfinder_paths/core/utils/transaction.py +57 -8
- wayfinder_paths/core/utils/web3.py +8 -3
- wayfinder_paths/mcp/__init__.py +5 -0
- wayfinder_paths/mcp/preview.py +185 -0
- wayfinder_paths/mcp/scripting.py +84 -0
- wayfinder_paths/mcp/server.py +52 -0
- wayfinder_paths/mcp/state/profile_store.py +195 -0
- wayfinder_paths/mcp/state/store.py +89 -0
- wayfinder_paths/mcp/test_scripting.py +267 -0
- wayfinder_paths/mcp/tools/__init__.py +0 -0
- wayfinder_paths/mcp/tools/balances.py +290 -0
- wayfinder_paths/mcp/tools/discovery.py +158 -0
- wayfinder_paths/mcp/tools/execute.py +770 -0
- wayfinder_paths/mcp/tools/hyperliquid.py +931 -0
- wayfinder_paths/mcp/tools/quotes.py +288 -0
- wayfinder_paths/mcp/tools/run_script.py +286 -0
- wayfinder_paths/mcp/tools/strategies.py +188 -0
- wayfinder_paths/mcp/tools/tokens.py +46 -0
- wayfinder_paths/mcp/tools/wallets.py +354 -0
- wayfinder_paths/mcp/utils.py +129 -0
- wayfinder_paths/policies/enso.py +1 -2
- wayfinder_paths/policies/hyper_evm.py +6 -3
- wayfinder_paths/policies/hyperlend.py +1 -2
- wayfinder_paths/policies/hyperliquid.py +1 -1
- wayfinder_paths/policies/lifi.py +18 -0
- wayfinder_paths/policies/moonwell.py +12 -7
- wayfinder_paths/policies/prjx.py +1 -3
- wayfinder_paths/policies/util.py +8 -2
- wayfinder_paths/run_strategy.py +97 -300
- wayfinder_paths/strategies/basis_trading_strategy/constants.py +3 -1
- wayfinder_paths/strategies/basis_trading_strategy/strategy.py +47 -133
- wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +24 -53
- wayfinder_paths/strategies/boros_hype_strategy/__init__.py +3 -0
- wayfinder_paths/strategies/boros_hype_strategy/boros_ops_mixin.py +450 -0
- wayfinder_paths/strategies/boros_hype_strategy/constants.py +255 -0
- wayfinder_paths/strategies/boros_hype_strategy/examples.json +37 -0
- wayfinder_paths/strategies/boros_hype_strategy/hyperevm_ops_mixin.py +114 -0
- wayfinder_paths/strategies/boros_hype_strategy/hyperliquid_ops_mixin.py +642 -0
- wayfinder_paths/strategies/boros_hype_strategy/manifest.yaml +36 -0
- wayfinder_paths/strategies/boros_hype_strategy/planner.py +460 -0
- wayfinder_paths/strategies/boros_hype_strategy/risk_ops_mixin.py +886 -0
- wayfinder_paths/strategies/boros_hype_strategy/snapshot_mixin.py +494 -0
- wayfinder_paths/strategies/boros_hype_strategy/strategy.py +1194 -0
- wayfinder_paths/strategies/boros_hype_strategy/test_planner_golden.py +374 -0
- wayfinder_paths/{templates/strategy → strategies/boros_hype_strategy}/test_strategy.py +99 -63
- wayfinder_paths/strategies/boros_hype_strategy/types.py +365 -0
- wayfinder_paths/strategies/boros_hype_strategy/withdraw_mixin.py +997 -0
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +15 -23
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +27 -62
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +84 -58
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +5 -15
- wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +69 -164
- wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +43 -76
- wayfinder_paths/tests/test_mcp_quote_swap.py +165 -0
- wayfinder_paths/tests/test_test_coverage.py +1 -4
- wayfinder_paths-0.1.24.dist-info/METADATA +378 -0
- wayfinder_paths-0.1.24.dist-info/RECORD +185 -0
- {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.24.dist-info}/WHEEL +1 -1
- wayfinder_paths/core/clients/WalletClient.py +0 -41
- wayfinder_paths/core/engine/StrategyJob.py +0 -110
- wayfinder_paths/core/services/test_local_evm_txn.py +0 -145
- wayfinder_paths/scripts/create_strategy.py +0 -139
- wayfinder_paths/scripts/make_wallets.py +0 -142
- wayfinder_paths/templates/adapter/README.md +0 -150
- wayfinder_paths/templates/adapter/adapter.py +0 -16
- wayfinder_paths/templates/adapter/examples.json +0 -8
- wayfinder_paths/templates/adapter/test_adapter.py +0 -30
- wayfinder_paths/templates/strategy/README.md +0 -186
- wayfinder_paths/templates/strategy/examples.json +0 -11
- wayfinder_paths/templates/strategy/strategy.py +0 -35
- wayfinder_paths/tests/test_smoke_manifest.py +0 -63
- wayfinder_paths-0.1.22.dist-info/METADATA +0 -355
- wayfinder_paths-0.1.22.dist-info/RECORD +0 -129
- /wayfinder_paths/{scripts → mcp/state}/__init__.py +0 -0
- {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.24.dist-info}/LICENSE +0 -0
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
from typing import Any
|
|
2
|
-
|
|
3
|
-
from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class MyAdapter(BaseAdapter):
|
|
7
|
-
adapter_type: str = "MY_ADAPTER"
|
|
8
|
-
|
|
9
|
-
def __init__(self, config: dict[str, Any] | None = None):
|
|
10
|
-
super().__init__("my_adapter", config)
|
|
11
|
-
|
|
12
|
-
async def connect(self) -> bool:
|
|
13
|
-
return True
|
|
14
|
-
|
|
15
|
-
async def example_operation(self, **kwargs) -> tuple[bool, str]:
|
|
16
|
-
return (True, "example.op executed")
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
|
|
3
|
-
# TODO: Replace MyAdapter with your actual adapter class name
|
|
4
|
-
from .adapter import MyAdapter
|
|
5
|
-
|
|
6
|
-
# For mocking clients, uncomment when needed:
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class TestMyAdapter:
|
|
10
|
-
@pytest.fixture
|
|
11
|
-
def adapter(self):
|
|
12
|
-
return MyAdapter(config={})
|
|
13
|
-
|
|
14
|
-
@pytest.mark.asyncio
|
|
15
|
-
async def test_health_check(self, adapter):
|
|
16
|
-
health = await adapter.health_check()
|
|
17
|
-
assert isinstance(health, dict)
|
|
18
|
-
assert health.get("status") in {"healthy", "unhealthy", "error"}
|
|
19
|
-
|
|
20
|
-
@pytest.mark.asyncio
|
|
21
|
-
async def test_connect(self, adapter):
|
|
22
|
-
ok = await adapter.connect()
|
|
23
|
-
assert isinstance(ok, bool)
|
|
24
|
-
|
|
25
|
-
def test_capabilities(self, adapter):
|
|
26
|
-
assert hasattr(adapter, "adapter_type")
|
|
27
|
-
|
|
28
|
-
@pytest.mark.asyncio
|
|
29
|
-
async def test_basic_functionality(self, adapter):
|
|
30
|
-
assert adapter is not None
|
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
# Strategy Template
|
|
2
|
-
|
|
3
|
-
This template provides scaffolding for a new strategy.
|
|
4
|
-
|
|
5
|
-
## Quick Start
|
|
6
|
-
|
|
7
|
-
1. Copy the template:
|
|
8
|
-
```bash
|
|
9
|
-
cp -r wayfinder_paths/templates/strategy wayfinder_paths/strategies/my_strategy
|
|
10
|
-
```
|
|
11
|
-
Or use the convenience command:
|
|
12
|
-
```bash
|
|
13
|
-
just create-strategy "My Strategy Name"
|
|
14
|
-
```
|
|
15
|
-
2. Rename the class in `strategy.py` to match your strategy name.
|
|
16
|
-
3. Implement the required methods (`deposit`, `update`, `exit`, `_status`).
|
|
17
|
-
4. Add tests in `test_strategy.py`.
|
|
18
|
-
5. Fill out `examples.json` with sample CLI invocations.
|
|
19
|
-
|
|
20
|
-
## Directory Structure
|
|
21
|
-
|
|
22
|
-
```
|
|
23
|
-
my_strategy/
|
|
24
|
-
├── strategy.py # Strategy implementation
|
|
25
|
-
├── examples.json # Example CLI payloads
|
|
26
|
-
├── test_strategy.py # Pytest tests
|
|
27
|
-
└── README.md # Strategy documentation
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Required Methods
|
|
31
|
-
|
|
32
|
-
```python
|
|
33
|
-
async def deposit(self, main_token_amount: float, gas_token_amount: float) -> StatusTuple:
|
|
34
|
-
"""Move funds from main wallet into strategy wallet and deploy capital."""
|
|
35
|
-
|
|
36
|
-
async def update(self) -> StatusTuple:
|
|
37
|
-
"""Periodic rebalance/optimization loop."""
|
|
38
|
-
|
|
39
|
-
async def exit(self, **kwargs) -> StatusTuple:
|
|
40
|
-
"""Transfer funds from strategy wallet back to main wallet."""
|
|
41
|
-
|
|
42
|
-
async def _status(self) -> StatusDict:
|
|
43
|
-
"""Return portfolio_value, net_deposit, and strategy_status."""
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Optional Methods
|
|
47
|
-
|
|
48
|
-
```python
|
|
49
|
-
async def withdraw(self, **kwargs) -> StatusTuple:
|
|
50
|
-
"""Unwind positions. Default implementation unwinds ledger operations."""
|
|
51
|
-
|
|
52
|
-
async def partial_liquidate(self, usd_value: float) -> tuple[bool, LiquidationResult]:
|
|
53
|
-
"""Liquidate a portion of the position by USD value."""
|
|
54
|
-
|
|
55
|
-
async def setup(self) -> None:
|
|
56
|
-
"""Post-construction initialization."""
|
|
57
|
-
|
|
58
|
-
async def health_check(self) -> dict:
|
|
59
|
-
"""Check strategy and adapter health."""
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
## Strategy Structure
|
|
63
|
-
|
|
64
|
-
```python
|
|
65
|
-
from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
|
|
66
|
-
from wayfinder_paths.adapters.balance_adapter.adapter import BalanceAdapter
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class MyStrategy(Strategy):
|
|
70
|
-
name = "My Strategy"
|
|
71
|
-
|
|
72
|
-
def __init__(self, config: dict | None = None, **kwargs):
|
|
73
|
-
super().__init__(config, **kwargs)
|
|
74
|
-
self.config = config or {}
|
|
75
|
-
|
|
76
|
-
# Initialize and register adapters
|
|
77
|
-
balance_adapter = BalanceAdapter(
|
|
78
|
-
self.config,
|
|
79
|
-
main_wallet_signing_callback=kwargs.get("main_wallet_signing_callback"),
|
|
80
|
-
strategy_wallet_signing_callback=kwargs.get("strategy_wallet_signing_callback"),
|
|
81
|
-
)
|
|
82
|
-
self.register_adapters([balance_adapter])
|
|
83
|
-
self.balance_adapter = balance_adapter
|
|
84
|
-
|
|
85
|
-
async def deposit(
|
|
86
|
-
self, main_token_amount: float = 0.0, gas_token_amount: float = 0.0
|
|
87
|
-
) -> StatusTuple:
|
|
88
|
-
if main_token_amount <= 0:
|
|
89
|
-
return (False, "Nothing to deposit")
|
|
90
|
-
|
|
91
|
-
# Implement deposit logic
|
|
92
|
-
return (True, f"Deposited {main_token_amount} tokens")
|
|
93
|
-
|
|
94
|
-
async def update(self) -> StatusTuple:
|
|
95
|
-
# Implement rebalancing logic
|
|
96
|
-
return (True, "Update complete")
|
|
97
|
-
|
|
98
|
-
async def exit(self, **kwargs) -> StatusTuple:
|
|
99
|
-
# Implement exit logic
|
|
100
|
-
return (True, "Exit complete")
|
|
101
|
-
|
|
102
|
-
async def _status(self) -> StatusDict:
|
|
103
|
-
return {
|
|
104
|
-
"portfolio_value": 0.0,
|
|
105
|
-
"net_deposit": 0.0,
|
|
106
|
-
"strategy_status": {"message": "healthy"},
|
|
107
|
-
"gas_available": 0.0,
|
|
108
|
-
"gassed_up": True,
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
## Testing
|
|
113
|
-
|
|
114
|
-
Create `test_strategy.py` using `examples.json`:
|
|
115
|
-
|
|
116
|
-
```python
|
|
117
|
-
import pytest
|
|
118
|
-
from pathlib import Path
|
|
119
|
-
from tests.test_utils import load_strategy_examples
|
|
120
|
-
from .strategy import MyStrategy
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
@pytest.mark.asyncio
|
|
124
|
-
async def test_smoke():
|
|
125
|
-
"""Basic strategy lifecycle test."""
|
|
126
|
-
examples = load_strategy_examples(Path(__file__))
|
|
127
|
-
smoke_example = examples["smoke"]
|
|
128
|
-
|
|
129
|
-
s = MyStrategy()
|
|
130
|
-
|
|
131
|
-
# Deposit
|
|
132
|
-
deposit_params = smoke_example.get("deposit", {})
|
|
133
|
-
ok, _ = await s.deposit(**deposit_params)
|
|
134
|
-
assert ok
|
|
135
|
-
|
|
136
|
-
# Update
|
|
137
|
-
ok, _ = await s.update()
|
|
138
|
-
assert ok
|
|
139
|
-
|
|
140
|
-
# Status
|
|
141
|
-
st = await s._status()
|
|
142
|
-
assert "portfolio_value" in st
|
|
143
|
-
assert "net_deposit" in st
|
|
144
|
-
assert "strategy_status" in st
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
Run tests:
|
|
148
|
-
|
|
149
|
-
```bash
|
|
150
|
-
poetry run pytest wayfinder_paths/strategies/my_strategy/ -v
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
## Running the Strategy
|
|
154
|
-
|
|
155
|
-
```bash
|
|
156
|
-
# Install dependencies
|
|
157
|
-
poetry install
|
|
158
|
-
|
|
159
|
-
# Generate wallets
|
|
160
|
-
just create-wallets
|
|
161
|
-
just create-wallet my_strategy
|
|
162
|
-
|
|
163
|
-
# Configure API key in config.json
|
|
164
|
-
|
|
165
|
-
# Check status
|
|
166
|
-
poetry run python wayfinder_paths/run_strategy.py my_strategy --action status --config config.json
|
|
167
|
-
|
|
168
|
-
# Deposit
|
|
169
|
-
poetry run python wayfinder_paths/run_strategy.py my_strategy \
|
|
170
|
-
--action deposit --main-token-amount 100 --gas-token-amount 0.01 --config config.json
|
|
171
|
-
|
|
172
|
-
# Run update
|
|
173
|
-
poetry run python wayfinder_paths/run_strategy.py my_strategy --action update --config config.json
|
|
174
|
-
|
|
175
|
-
# Withdraw
|
|
176
|
-
poetry run python wayfinder_paths/run_strategy.py my_strategy --action withdraw --config config.json
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
## Best Practices
|
|
180
|
-
|
|
181
|
-
- Return `(success: bool, message: str)` tuples from all action methods
|
|
182
|
-
- Always populate `portfolio_value`, `net_deposit`, and `strategy_status` in `_status`
|
|
183
|
-
- Register adapters via `register_adapters()` in `__init__`
|
|
184
|
-
- Use adapters for external operations, not clients directly
|
|
185
|
-
- Keep strategy logic clear and well-documented
|
|
186
|
-
- Add error handling with informative messages
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class MyStrategy(Strategy):
|
|
5
|
-
name = "My Strategy"
|
|
6
|
-
description = "Short description of what the strategy does."
|
|
7
|
-
summary = "One-line summary for discovery."
|
|
8
|
-
|
|
9
|
-
def __init__(self):
|
|
10
|
-
super().__init__()
|
|
11
|
-
|
|
12
|
-
async def setup(self):
|
|
13
|
-
return None
|
|
14
|
-
|
|
15
|
-
async def deposit(
|
|
16
|
-
self, main_token_amount: float, gas_token_amount: float
|
|
17
|
-
) -> StatusTuple:
|
|
18
|
-
return (True, "Deposit successful")
|
|
19
|
-
|
|
20
|
-
async def withdraw(self, amount: float | None = None) -> StatusTuple:
|
|
21
|
-
return await super().withdraw(amount=amount)
|
|
22
|
-
|
|
23
|
-
async def update(self) -> StatusTuple:
|
|
24
|
-
return (True, "Update successful")
|
|
25
|
-
|
|
26
|
-
async def _status(self) -> StatusDict:
|
|
27
|
-
return {
|
|
28
|
-
"portfolio_value": 0.0,
|
|
29
|
-
"net_deposit": 0.0,
|
|
30
|
-
"strategy_status": {},
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
@staticmethod
|
|
34
|
-
def policies() -> list[str]:
|
|
35
|
-
return []
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
|
|
3
|
-
from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
|
|
4
|
-
from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class FakeAdapter(BaseAdapter):
|
|
8
|
-
adapter_type = "FAKE"
|
|
9
|
-
|
|
10
|
-
async def connect(self) -> bool:
|
|
11
|
-
return True
|
|
12
|
-
|
|
13
|
-
async def get_balance(self, asset: str):
|
|
14
|
-
return {"asset": asset, "amount": 100}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class FakeLedgerAdapter(BaseAdapter):
|
|
18
|
-
adapter_type = "LEDGER"
|
|
19
|
-
|
|
20
|
-
async def connect(self) -> bool:
|
|
21
|
-
return True
|
|
22
|
-
|
|
23
|
-
async def record_strategy_snapshot(self, **kwargs):
|
|
24
|
-
pass
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class FakeStrategy(Strategy):
|
|
28
|
-
name = "Fake Strategy"
|
|
29
|
-
|
|
30
|
-
async def deposit(self, amount: float = 0) -> StatusTuple:
|
|
31
|
-
return (True, "deposited")
|
|
32
|
-
|
|
33
|
-
async def update(self) -> StatusTuple:
|
|
34
|
-
return (True, "updated")
|
|
35
|
-
|
|
36
|
-
async def withdraw(self, amount: float = 0) -> StatusTuple:
|
|
37
|
-
return (True, "withdrew")
|
|
38
|
-
|
|
39
|
-
async def _status(self) -> StatusDict:
|
|
40
|
-
return {"total_earned": 0.0, "strategy_status": {"ok": True}}
|
|
41
|
-
|
|
42
|
-
@staticmethod
|
|
43
|
-
def policy() -> str:
|
|
44
|
-
return "wallet.id == 'TEST'"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
@pytest.mark.asyncio
|
|
48
|
-
async def test_smoke_deposit_update_withdraw_status():
|
|
49
|
-
s = FakeStrategy(
|
|
50
|
-
config={
|
|
51
|
-
"strategy_wallet": {"address": "0x1234567890123456789012345678901234567890"}
|
|
52
|
-
}
|
|
53
|
-
)
|
|
54
|
-
s.register_adapters([FakeAdapter("fake")])
|
|
55
|
-
s.ledger_adapter = FakeLedgerAdapter("ledger")
|
|
56
|
-
ok, msg = await s.deposit(amount=1)
|
|
57
|
-
assert ok
|
|
58
|
-
ok, msg = await s.update()
|
|
59
|
-
assert ok
|
|
60
|
-
ok, msg = await s.withdraw(amount=1)
|
|
61
|
-
assert ok
|
|
62
|
-
st = await s.status()
|
|
63
|
-
assert "total_earned" in st
|