wayfinder-paths 0.1.4__py3-none-any.whl → 0.1.5__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/CONFIG_GUIDE.md +14 -14
- wayfinder_paths/__init__.py +3 -3
- wayfinder_paths/adapters/balance_adapter/README.md +10 -10
- wayfinder_paths/adapters/balance_adapter/adapter.py +10 -9
- wayfinder_paths/adapters/balance_adapter/examples.json +1 -1
- wayfinder_paths/adapters/brap_adapter/README.md +1 -1
- wayfinder_paths/adapters/brap_adapter/adapter.py +28 -21
- wayfinder_paths/adapters/hyperlend_adapter/adapter.py +33 -26
- wayfinder_paths/adapters/ledger_adapter/README.md +26 -39
- wayfinder_paths/adapters/ledger_adapter/adapter.py +78 -75
- wayfinder_paths/adapters/ledger_adapter/examples.json +10 -4
- wayfinder_paths/adapters/ledger_adapter/manifest.yaml +4 -4
- wayfinder_paths/adapters/ledger_adapter/test_adapter.py +31 -26
- wayfinder_paths/adapters/pool_adapter/README.md +1 -13
- wayfinder_paths/adapters/pool_adapter/adapter.py +12 -19
- wayfinder_paths/adapters/token_adapter/adapter.py +8 -4
- wayfinder_paths/core/__init__.py +3 -3
- wayfinder_paths/core/adapters/BaseAdapter.py +20 -3
- wayfinder_paths/core/adapters/models.py +41 -0
- wayfinder_paths/core/clients/BRAPClient.py +21 -2
- wayfinder_paths/core/clients/ClientManager.py +42 -63
- wayfinder_paths/core/clients/HyperlendClient.py +46 -5
- wayfinder_paths/core/clients/LedgerClient.py +350 -124
- wayfinder_paths/core/clients/PoolClient.py +51 -19
- wayfinder_paths/core/clients/SimulationClient.py +16 -4
- wayfinder_paths/core/clients/TokenClient.py +34 -18
- wayfinder_paths/core/clients/TransactionClient.py +18 -2
- wayfinder_paths/core/clients/WalletClient.py +35 -4
- wayfinder_paths/core/clients/WayfinderClient.py +16 -5
- wayfinder_paths/core/clients/protocols.py +69 -62
- wayfinder_paths/core/clients/sdk_example.py +0 -5
- wayfinder_paths/core/config.py +192 -103
- wayfinder_paths/core/constants/base.py +17 -0
- wayfinder_paths/core/engine/{VaultJob.py → StrategyJob.py} +25 -19
- wayfinder_paths/core/engine/__init__.py +2 -2
- wayfinder_paths/core/services/base.py +6 -4
- wayfinder_paths/core/services/local_evm_txn.py +3 -2
- wayfinder_paths/core/settings.py +2 -2
- wayfinder_paths/core/strategies/Strategy.py +123 -37
- wayfinder_paths/core/utils/evm_helpers.py +12 -10
- wayfinder_paths/core/wallets/README.md +3 -3
- wayfinder_paths/core/wallets/WalletManager.py +3 -3
- wayfinder_paths/run_strategy.py +26 -24
- wayfinder_paths/scripts/make_wallets.py +6 -6
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md +6 -6
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +36 -156
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +6 -6
- wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +11 -11
- wayfinder_paths/strategies/stablecoin_yield_strategy/manifest.yaml +1 -1
- wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +92 -92
- wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +6 -6
- wayfinder_paths/templates/adapter/README.md +1 -1
- wayfinder_paths/templates/adapter/test_adapter.py +1 -1
- wayfinder_paths/templates/strategy/README.md +4 -4
- wayfinder_paths/templates/strategy/test_strategy.py +7 -7
- wayfinder_paths/tests/test_test_coverage.py +5 -5
- {wayfinder_paths-0.1.4.dist-info → wayfinder_paths-0.1.5.dist-info}/METADATA +46 -47
- {wayfinder_paths-0.1.4.dist-info → wayfinder_paths-0.1.5.dist-info}/RECORD +60 -59
- {wayfinder_paths-0.1.4.dist-info → wayfinder_paths-0.1.5.dist-info}/LICENSE +0 -0
- {wayfinder_paths-0.1.4.dist-info → wayfinder_paths-0.1.5.dist-info}/WHEEL +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# Ledger Adapter
|
|
2
2
|
|
|
3
|
-
A Wayfinder adapter that provides high-level operations for
|
|
3
|
+
A Wayfinder adapter that provides high-level operations for strategy transaction history and bookkeeping. This adapter wraps the `LedgerClient` to offer strategy-friendly methods for recording and retrieving strategy operations.
|
|
4
4
|
|
|
5
5
|
## Capabilities
|
|
6
6
|
|
|
7
|
-
- `ledger.read`: Read
|
|
7
|
+
- `ledger.read`: Read strategy transaction data and net deposits
|
|
8
8
|
- `ledger.write`: Record deposits, withdrawals, and operations
|
|
9
|
-
- `
|
|
10
|
-
- `
|
|
11
|
-
- `
|
|
12
|
-
- `
|
|
9
|
+
- `strategy.transactions`: Access strategy transaction history
|
|
10
|
+
- `strategy.deposits`: Record deposit transactions
|
|
11
|
+
- `strategy.withdrawals`: Record withdrawal transactions
|
|
12
|
+
- `strategy.operations`: Record strategy operations (swaps, rebalances, etc.)
|
|
13
13
|
|
|
14
14
|
## Configuration
|
|
15
15
|
|
|
@@ -31,10 +31,10 @@ from wayfinder_paths.adapters.ledger_adapter.adapter import LedgerAdapter
|
|
|
31
31
|
adapter = LedgerAdapter()
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
### Get
|
|
34
|
+
### Get Strategy Transaction History
|
|
35
35
|
|
|
36
36
|
```python
|
|
37
|
-
success, data = await adapter.
|
|
37
|
+
success, data = await adapter.get_strategy_transactions(
|
|
38
38
|
wallet_address="0x1234567890123456789012345678901234567890",
|
|
39
39
|
limit=10,
|
|
40
40
|
offset=0
|
|
@@ -49,7 +49,7 @@ else:
|
|
|
49
49
|
### Get Net Deposit Amount
|
|
50
50
|
|
|
51
51
|
```python
|
|
52
|
-
success, data = await adapter.
|
|
52
|
+
success, data = await adapter.get_strategy_net_deposit(
|
|
53
53
|
wallet_address="0x1234567890123456789012345678901234567890"
|
|
54
54
|
)
|
|
55
55
|
if success:
|
|
@@ -93,51 +93,38 @@ else:
|
|
|
93
93
|
print(f"Error: {data}")
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
-
### Record an Operation
|
|
96
|
+
### Record an Operation
|
|
97
97
|
|
|
98
98
|
```python
|
|
99
|
+
from wayfinder_paths.adapters.ledger_adapter.models import SWAP
|
|
100
|
+
|
|
101
|
+
operation = SWAP(
|
|
102
|
+
from_token_id="0xA0b86...",
|
|
103
|
+
to_token_id="0xB1c97...",
|
|
104
|
+
from_amount="1000000000000000000",
|
|
105
|
+
to_amount="995000000000000000",
|
|
106
|
+
from_amount_usd=1000.0,
|
|
107
|
+
to_amount_usd=995.0,
|
|
108
|
+
)
|
|
109
|
+
|
|
99
110
|
success, op = await adapter.record_operation(
|
|
100
|
-
wallet_address=
|
|
101
|
-
operation_data=
|
|
102
|
-
"type": "SWAP",
|
|
103
|
-
"from_token": "...",
|
|
104
|
-
"to_token": "...",
|
|
105
|
-
"amount_in": "1000000000000000000",
|
|
106
|
-
"amount_out": "995000000000000000",
|
|
107
|
-
},
|
|
111
|
+
wallet_address=strategy_address,
|
|
112
|
+
operation_data=operation,
|
|
108
113
|
usd_value="1000.00",
|
|
109
114
|
strategy_name="StablecoinYieldStrategy",
|
|
110
115
|
)
|
|
111
116
|
|
|
112
|
-
success, cashflow = await adapter.record_cashflow(
|
|
113
|
-
wallet_address=vault_address,
|
|
114
|
-
block_timestamp=int(time.time()),
|
|
115
|
-
token_addr="0x...",
|
|
116
|
-
amount="250000000000000000",
|
|
117
|
-
description="reward",
|
|
118
|
-
strategy_name="StablecoinYieldStrategy",
|
|
119
|
-
)
|
|
120
117
|
```
|
|
121
118
|
|
|
122
119
|
### Latest Transactions and Summaries
|
|
123
120
|
|
|
124
121
|
```python
|
|
125
|
-
success, latest = await adapter.
|
|
126
|
-
success, summary = await adapter.get_transaction_summary(wallet_address=
|
|
122
|
+
success, latest = await adapter.get_strategy_latest_transactions(wallet_address=strategy_address)
|
|
123
|
+
success, summary = await adapter.get_transaction_summary(wallet_address=strategy_address, limit=5)
|
|
127
124
|
if success:
|
|
128
125
|
print(f"Total transactions: {summary.get('total_transactions')}")
|
|
129
126
|
```
|
|
130
127
|
|
|
131
|
-
## API Endpoints
|
|
132
|
-
|
|
133
|
-
The adapter uses the following Wayfinder API endpoints:
|
|
134
|
-
|
|
135
|
-
- `GET /api/v1/public/vaults/transactions/` - Get vault transactions
|
|
136
|
-
- `GET /api/v1/public/vaults/net-deposit/` - Get net deposit amount
|
|
137
|
-
- `POST /api/v1/public/vaults/deposits/` - Record a deposit
|
|
138
|
-
- `POST /api/v1/public/vaults/withdrawals/` - Record a withdrawal
|
|
139
|
-
- `POST /api/v1/public/vaults/operations/` - Record an operation
|
|
140
|
-
|
|
141
128
|
## Error Handling
|
|
142
129
|
|
|
143
130
|
All methods return a tuple of `(success: bool, data: Any)` where:
|
|
@@ -149,7 +136,7 @@ All methods return a tuple of `(success: bool, data: Any)` where:
|
|
|
149
136
|
Run the adapter tests:
|
|
150
137
|
|
|
151
138
|
```bash
|
|
152
|
-
pytest wayfinder_paths/
|
|
139
|
+
pytest wayfinder_paths/adapters/ledger_adapter/test_adapter.py -v
|
|
153
140
|
```
|
|
154
141
|
|
|
155
142
|
## Dependencies
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
|
|
3
3
|
from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
|
|
4
|
-
from wayfinder_paths.core.
|
|
4
|
+
from wayfinder_paths.core.adapters.models import Operation
|
|
5
|
+
from wayfinder_paths.core.clients.LedgerClient import (
|
|
6
|
+
LedgerClient,
|
|
7
|
+
NetDeposit,
|
|
8
|
+
StrategyTransactionList,
|
|
9
|
+
TransactionRecord,
|
|
10
|
+
)
|
|
11
|
+
from wayfinder_paths.core.strategies.Strategy import StatusDict
|
|
5
12
|
|
|
6
13
|
|
|
7
14
|
class LedgerAdapter(BaseAdapter):
|
|
8
15
|
"""
|
|
9
|
-
Ledger adapter for
|
|
16
|
+
Ledger adapter for strategy transaction history and bookkeeping operations.
|
|
10
17
|
|
|
11
18
|
Provides high-level operations for:
|
|
12
|
-
- Fetching
|
|
19
|
+
- Fetching strategy transaction history
|
|
13
20
|
- Getting net deposit amounts
|
|
14
21
|
- Getting last rotation time
|
|
15
|
-
- Recording deposits, withdrawals,
|
|
22
|
+
- Recording deposits, withdrawals, and operations
|
|
16
23
|
"""
|
|
17
24
|
|
|
18
25
|
adapter_type: str = "LEDGER"
|
|
@@ -25,14 +32,14 @@ class LedgerAdapter(BaseAdapter):
|
|
|
25
32
|
super().__init__("ledger_adapter", config)
|
|
26
33
|
self.ledger_client = ledger_client or LedgerClient()
|
|
27
34
|
|
|
28
|
-
async def
|
|
35
|
+
async def get_strategy_transactions(
|
|
29
36
|
self, wallet_address: str, limit: int = 50, offset: int = 0
|
|
30
|
-
) -> tuple[bool,
|
|
37
|
+
) -> tuple[bool, StrategyTransactionList | str]:
|
|
31
38
|
"""
|
|
32
|
-
Get paginated
|
|
39
|
+
Get paginated strategy transaction history.
|
|
33
40
|
|
|
34
41
|
Args:
|
|
35
|
-
wallet_address:
|
|
42
|
+
wallet_address: Strategy wallet address
|
|
36
43
|
limit: Maximum number of transactions to return
|
|
37
44
|
offset: Number of transactions to skip
|
|
38
45
|
|
|
@@ -40,52 +47,54 @@ class LedgerAdapter(BaseAdapter):
|
|
|
40
47
|
Tuple of (success, data) where data is transaction list or error message
|
|
41
48
|
"""
|
|
42
49
|
try:
|
|
43
|
-
data = await self.ledger_client.
|
|
50
|
+
data = await self.ledger_client.get_strategy_transactions(
|
|
44
51
|
wallet_address=wallet_address, limit=limit, offset=offset
|
|
45
52
|
)
|
|
46
53
|
return (True, data)
|
|
47
54
|
except Exception as e:
|
|
48
|
-
self.logger.error(f"Error fetching
|
|
55
|
+
self.logger.error(f"Error fetching strategy transactions: {e}")
|
|
49
56
|
return (False, str(e))
|
|
50
57
|
|
|
51
|
-
async def
|
|
58
|
+
async def get_strategy_net_deposit(
|
|
59
|
+
self, wallet_address: str
|
|
60
|
+
) -> tuple[bool, NetDeposit | str]:
|
|
52
61
|
"""
|
|
53
|
-
Get net deposit amount (deposits - withdrawals) for a
|
|
62
|
+
Get net deposit amount (deposits - withdrawals) for a strategy.
|
|
54
63
|
|
|
55
64
|
Args:
|
|
56
|
-
wallet_address:
|
|
65
|
+
wallet_address: Strategy wallet address
|
|
57
66
|
|
|
58
67
|
Returns:
|
|
59
68
|
Tuple of (success, data) where data contains net_deposit or error message
|
|
60
69
|
"""
|
|
61
70
|
try:
|
|
62
|
-
data = await self.ledger_client.
|
|
71
|
+
data = await self.ledger_client.get_strategy_net_deposit(
|
|
63
72
|
wallet_address=wallet_address
|
|
64
73
|
)
|
|
65
74
|
return (True, data)
|
|
66
75
|
except Exception as e:
|
|
67
|
-
self.logger.error(f"Error fetching
|
|
76
|
+
self.logger.error(f"Error fetching strategy net deposit: {e}")
|
|
68
77
|
return (False, str(e))
|
|
69
78
|
|
|
70
|
-
async def
|
|
79
|
+
async def get_strategy_latest_transactions(
|
|
71
80
|
self, wallet_address: str
|
|
72
|
-
) -> tuple[bool,
|
|
81
|
+
) -> tuple[bool, StrategyTransactionList | str]:
|
|
73
82
|
"""
|
|
74
|
-
Get the latest transactions for a
|
|
83
|
+
Get the latest transactions for a strategy.
|
|
75
84
|
|
|
76
85
|
Args:
|
|
77
|
-
wallet_address:
|
|
86
|
+
wallet_address: Strategy wallet address
|
|
78
87
|
|
|
79
88
|
Returns:
|
|
80
89
|
Tuple of (success, data) where data contains latest transactions or error message
|
|
81
90
|
"""
|
|
82
91
|
try:
|
|
83
|
-
data = await self.ledger_client.
|
|
92
|
+
data = await self.ledger_client.get_strategy_latest_transactions(
|
|
84
93
|
wallet_address=wallet_address
|
|
85
94
|
)
|
|
86
95
|
return (True, data)
|
|
87
96
|
except Exception as e:
|
|
88
|
-
self.logger.error(f"Error fetching
|
|
97
|
+
self.logger.error(f"Error fetching strategy last transactions: {e}")
|
|
89
98
|
return (False, str(e))
|
|
90
99
|
|
|
91
100
|
async def record_deposit(
|
|
@@ -97,12 +106,12 @@ class LedgerAdapter(BaseAdapter):
|
|
|
97
106
|
usd_value: str | float,
|
|
98
107
|
data: dict[str, Any] | None = None,
|
|
99
108
|
strategy_name: str | None = None,
|
|
100
|
-
) -> tuple[bool,
|
|
109
|
+
) -> tuple[bool, TransactionRecord | str]:
|
|
101
110
|
"""
|
|
102
|
-
Record a
|
|
111
|
+
Record a strategy deposit transaction.
|
|
103
112
|
|
|
104
113
|
Args:
|
|
105
|
-
wallet_address:
|
|
114
|
+
wallet_address: Strategy wallet address
|
|
106
115
|
chain_id: Blockchain chain ID
|
|
107
116
|
token_address: Token contract address
|
|
108
117
|
token_amount: Amount deposited (in token units)
|
|
@@ -114,7 +123,7 @@ class LedgerAdapter(BaseAdapter):
|
|
|
114
123
|
Tuple of (success, data) where data is transaction record or error message
|
|
115
124
|
"""
|
|
116
125
|
try:
|
|
117
|
-
result = await self.ledger_client.
|
|
126
|
+
result = await self.ledger_client.add_strategy_deposit(
|
|
118
127
|
wallet_address=wallet_address,
|
|
119
128
|
chain_id=chain_id,
|
|
120
129
|
token_address=token_address,
|
|
@@ -137,12 +146,12 @@ class LedgerAdapter(BaseAdapter):
|
|
|
137
146
|
usd_value: str | float,
|
|
138
147
|
data: dict[str, Any] | None = None,
|
|
139
148
|
strategy_name: str | None = None,
|
|
140
|
-
) -> tuple[bool,
|
|
149
|
+
) -> tuple[bool, TransactionRecord | str]:
|
|
141
150
|
"""
|
|
142
|
-
Record a
|
|
151
|
+
Record a strategy withdrawal transaction.
|
|
143
152
|
|
|
144
153
|
Args:
|
|
145
|
-
wallet_address:
|
|
154
|
+
wallet_address: Strategy wallet address
|
|
146
155
|
chain_id: Blockchain chain ID
|
|
147
156
|
token_address: Token contract address
|
|
148
157
|
token_amount: Amount withdrawn (in token units)
|
|
@@ -154,7 +163,7 @@ class LedgerAdapter(BaseAdapter):
|
|
|
154
163
|
Tuple of (success, data) where data is transaction record or error message
|
|
155
164
|
"""
|
|
156
165
|
try:
|
|
157
|
-
result = await self.ledger_client.
|
|
166
|
+
result = await self.ledger_client.add_strategy_withdraw(
|
|
158
167
|
wallet_address=wallet_address,
|
|
159
168
|
chain_id=chain_id,
|
|
160
169
|
token_address=token_address,
|
|
@@ -171,16 +180,16 @@ class LedgerAdapter(BaseAdapter):
|
|
|
171
180
|
async def record_operation(
|
|
172
181
|
self,
|
|
173
182
|
wallet_address: str,
|
|
174
|
-
operation_data:
|
|
183
|
+
operation_data: Operation,
|
|
175
184
|
usd_value: str | float,
|
|
176
185
|
strategy_name: str | None = None,
|
|
177
|
-
) -> tuple[bool,
|
|
186
|
+
) -> tuple[bool, TransactionRecord | str]:
|
|
178
187
|
"""
|
|
179
|
-
Record a
|
|
188
|
+
Record a strategy operation (e.g., swaps, rebalances) for bookkeeping.
|
|
180
189
|
|
|
181
190
|
Args:
|
|
182
|
-
wallet_address:
|
|
183
|
-
operation_data:
|
|
191
|
+
wallet_address: Strategy wallet address
|
|
192
|
+
operation_data: Operation model (SWAP, LEND, BORROW, etc.)
|
|
184
193
|
usd_value: USD value of the operation
|
|
185
194
|
strategy_name: Name of the strategy performing the operation
|
|
186
195
|
|
|
@@ -188,7 +197,7 @@ class LedgerAdapter(BaseAdapter):
|
|
|
188
197
|
Tuple of (success, data) where data is operation record or error message
|
|
189
198
|
"""
|
|
190
199
|
try:
|
|
191
|
-
result = await self.ledger_client.
|
|
200
|
+
result = await self.ledger_client.add_strategy_operation(
|
|
192
201
|
wallet_address=wallet_address,
|
|
193
202
|
operation_data=operation_data,
|
|
194
203
|
usd_value=usd_value,
|
|
@@ -199,58 +208,21 @@ class LedgerAdapter(BaseAdapter):
|
|
|
199
208
|
self.logger.error(f"Error recording operation: {e}")
|
|
200
209
|
return (False, str(e))
|
|
201
210
|
|
|
202
|
-
async def record_cashflow(
|
|
203
|
-
self,
|
|
204
|
-
wallet_address: str,
|
|
205
|
-
block_timestamp: int,
|
|
206
|
-
token_addr: str,
|
|
207
|
-
amount: str | int | float,
|
|
208
|
-
description: str,
|
|
209
|
-
strategy_name: str | None = None,
|
|
210
|
-
) -> tuple[bool, Any]:
|
|
211
|
-
"""
|
|
212
|
-
Record a vault cashflow (interest, funding, reward, or fee).
|
|
213
|
-
|
|
214
|
-
Args:
|
|
215
|
-
wallet_address: Vault wallet address
|
|
216
|
-
block_timestamp: Block timestamp (Unix timestamp)
|
|
217
|
-
token_addr: Token contract address
|
|
218
|
-
amount: Cashflow amount (in token units)
|
|
219
|
-
description: Cashflow type - must be one of: "interest", "funding", "reward", "fee"
|
|
220
|
-
strategy_name: Optional strategy name
|
|
221
|
-
|
|
222
|
-
Returns:
|
|
223
|
-
Tuple of (success, data) where data is cashflow record or error message
|
|
224
|
-
"""
|
|
225
|
-
try:
|
|
226
|
-
result = await self.ledger_client.add_vault_cashflow(
|
|
227
|
-
wallet_address=wallet_address,
|
|
228
|
-
block_timestamp=block_timestamp,
|
|
229
|
-
token_addr=token_addr,
|
|
230
|
-
amount=amount,
|
|
231
|
-
description=description,
|
|
232
|
-
strategy_name=strategy_name,
|
|
233
|
-
)
|
|
234
|
-
return (True, result)
|
|
235
|
-
except Exception as e:
|
|
236
|
-
self.logger.error(f"Error recording cashflow: {e}")
|
|
237
|
-
return (False, str(e))
|
|
238
|
-
|
|
239
211
|
async def get_transaction_summary(
|
|
240
212
|
self, wallet_address: str, limit: int = 10
|
|
241
213
|
) -> tuple[bool, Any]:
|
|
242
214
|
"""
|
|
243
|
-
Get a summary of recent
|
|
215
|
+
Get a summary of recent strategy transactions.
|
|
244
216
|
|
|
245
217
|
Args:
|
|
246
|
-
wallet_address:
|
|
218
|
+
wallet_address: Strategy wallet address
|
|
247
219
|
limit: Number of recent transactions to include
|
|
248
220
|
|
|
249
221
|
Returns:
|
|
250
222
|
Tuple of (success, data) where data is transaction summary or error message
|
|
251
223
|
"""
|
|
252
224
|
try:
|
|
253
|
-
success, transactions_data = await self.
|
|
225
|
+
success, transactions_data = await self.get_strategy_transactions(
|
|
254
226
|
wallet_address=wallet_address, limit=limit
|
|
255
227
|
)
|
|
256
228
|
|
|
@@ -284,3 +256,34 @@ class LedgerAdapter(BaseAdapter):
|
|
|
284
256
|
except Exception as e:
|
|
285
257
|
self.logger.error(f"Error creating transaction summary: {e}")
|
|
286
258
|
return (False, str(e))
|
|
259
|
+
|
|
260
|
+
async def record_strategy_snapshot(
|
|
261
|
+
self, wallet_address: str, strategy_status: StatusDict
|
|
262
|
+
) -> tuple[bool, None | str]:
|
|
263
|
+
"""
|
|
264
|
+
Record a strategy snapshot with current state.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
wallet_address: Strategy wallet address
|
|
268
|
+
strat_portfolio_value: Current portfolio value
|
|
269
|
+
net_deposit: Net deposit amount
|
|
270
|
+
strategy_status: Current strategy status dictionary
|
|
271
|
+
gas_available: Available gas amount
|
|
272
|
+
gassed_up: Whether the strategy is gassed up
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
Tuple of (success, None) on success or (False, error_message) on failure
|
|
276
|
+
"""
|
|
277
|
+
try:
|
|
278
|
+
await self.ledger_client.strategy_snapshot(
|
|
279
|
+
wallet_address=wallet_address,
|
|
280
|
+
strat_portfolio_value=strategy_status["portfolio_value"],
|
|
281
|
+
net_deposit=strategy_status["net_deposit"],
|
|
282
|
+
strategy_status=strategy_status["strategy_status"],
|
|
283
|
+
gas_available=strategy_status["gas_available"],
|
|
284
|
+
gassed_up=strategy_status["gassed_up"],
|
|
285
|
+
)
|
|
286
|
+
return (True, None)
|
|
287
|
+
except Exception as e:
|
|
288
|
+
self.logger.error(f"Error recording strategy snapshot: {e}")
|
|
289
|
+
return (False, str(e))
|
|
@@ -80,14 +80,20 @@
|
|
|
80
80
|
},
|
|
81
81
|
"record_operation": {
|
|
82
82
|
"description": "Record a vault operation (swap, rebalance, etc.)",
|
|
83
|
+
"note": "operation_data must be a Pydantic Operation model (currently only SWAP is implemented)",
|
|
83
84
|
"input": {
|
|
84
85
|
"wallet_address": "0x1234567890123456789012345678901234567890",
|
|
85
86
|
"operation_data": {
|
|
86
87
|
"type": "SWAP",
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
88
|
+
"from_token_id": "0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
89
|
+
"to_token_id": "0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
|
|
90
|
+
"from_amount": "1000000000000000000",
|
|
91
|
+
"to_amount": "995000000000000000",
|
|
92
|
+
"from_amount_usd": 1000.0,
|
|
93
|
+
"to_amount_usd": 995.0,
|
|
94
|
+
"transaction_hash": "0xabcdef...",
|
|
95
|
+
"transaction_status": "success",
|
|
96
|
+
"transaction_receipt": null
|
|
91
97
|
},
|
|
92
98
|
"usd_value": "1000.00",
|
|
93
99
|
"strategy_name": "StablecoinYieldStrategy"
|
|
@@ -3,9 +3,9 @@ entrypoint: "adapters.ledger_adapter.adapter.LedgerAdapter"
|
|
|
3
3
|
capabilities:
|
|
4
4
|
- "ledger.read"
|
|
5
5
|
- "ledger.write"
|
|
6
|
-
- "
|
|
7
|
-
- "
|
|
8
|
-
- "
|
|
9
|
-
- "
|
|
6
|
+
- "strategy.transactions"
|
|
7
|
+
- "strategy.deposits"
|
|
8
|
+
- "strategy.withdrawals"
|
|
9
|
+
- "strategy.operations"
|
|
10
10
|
dependencies:
|
|
11
11
|
- "LedgerClient"
|
|
@@ -24,8 +24,8 @@ class TestLedgerAdapter:
|
|
|
24
24
|
return LedgerAdapter()
|
|
25
25
|
|
|
26
26
|
@pytest.mark.asyncio
|
|
27
|
-
async def
|
|
28
|
-
"""Test successful
|
|
27
|
+
async def test_get_strategy_transactions_success(self, adapter, mock_ledger_client):
|
|
28
|
+
"""Test successful strategy transaction retrieval"""
|
|
29
29
|
mock_response = {
|
|
30
30
|
"transactions": [
|
|
31
31
|
{
|
|
@@ -37,11 +37,11 @@ class TestLedgerAdapter:
|
|
|
37
37
|
],
|
|
38
38
|
"total": 1,
|
|
39
39
|
}
|
|
40
|
-
mock_ledger_client.
|
|
40
|
+
mock_ledger_client.get_strategy_transactions = AsyncMock(
|
|
41
41
|
return_value=mock_response
|
|
42
42
|
)
|
|
43
43
|
|
|
44
|
-
success, data = await adapter.
|
|
44
|
+
success, data = await adapter.get_strategy_transactions(
|
|
45
45
|
wallet_address="0x1234567890123456789012345678901234567890",
|
|
46
46
|
limit=10,
|
|
47
47
|
offset=0,
|
|
@@ -49,20 +49,20 @@ class TestLedgerAdapter:
|
|
|
49
49
|
|
|
50
50
|
assert success is True
|
|
51
51
|
assert data == mock_response
|
|
52
|
-
mock_ledger_client.
|
|
52
|
+
mock_ledger_client.get_strategy_transactions.assert_called_once_with(
|
|
53
53
|
wallet_address="0x1234567890123456789012345678901234567890",
|
|
54
54
|
limit=10,
|
|
55
55
|
offset=0,
|
|
56
56
|
)
|
|
57
57
|
|
|
58
58
|
@pytest.mark.asyncio
|
|
59
|
-
async def
|
|
60
|
-
"""Test
|
|
61
|
-
mock_ledger_client.
|
|
59
|
+
async def test_get_strategy_transactions_failure(self, adapter, mock_ledger_client):
|
|
60
|
+
"""Test strategy transaction retrieval failure"""
|
|
61
|
+
mock_ledger_client.get_strategy_transactions = AsyncMock(
|
|
62
62
|
side_effect=Exception("API Error")
|
|
63
63
|
)
|
|
64
64
|
|
|
65
|
-
success, data = await adapter.
|
|
65
|
+
success, data = await adapter.get_strategy_transactions(
|
|
66
66
|
wallet_address="0x1234567890123456789012345678901234567890"
|
|
67
67
|
)
|
|
68
68
|
|
|
@@ -70,23 +70,25 @@ class TestLedgerAdapter:
|
|
|
70
70
|
assert "API Error" in data
|
|
71
71
|
|
|
72
72
|
@pytest.mark.asyncio
|
|
73
|
-
async def
|
|
74
|
-
"""Test successful
|
|
73
|
+
async def test_get_strategy_net_deposit_success(self, adapter, mock_ledger_client):
|
|
74
|
+
"""Test successful strategy net deposit retrieval"""
|
|
75
75
|
mock_response = {
|
|
76
76
|
"net_deposit": "1000.00",
|
|
77
77
|
"total_deposits": "1500.00",
|
|
78
78
|
"total_withdrawals": "500.00",
|
|
79
79
|
}
|
|
80
|
-
mock_ledger_client.
|
|
80
|
+
mock_ledger_client.get_strategy_net_deposit = AsyncMock(
|
|
81
|
+
return_value=mock_response
|
|
82
|
+
)
|
|
81
83
|
|
|
82
84
|
# Test
|
|
83
|
-
success, data = await adapter.
|
|
85
|
+
success, data = await adapter.get_strategy_net_deposit(
|
|
84
86
|
wallet_address="0x1234567890123456789012345678901234567890"
|
|
85
87
|
)
|
|
86
88
|
|
|
87
89
|
assert success is True
|
|
88
90
|
assert data == mock_response
|
|
89
|
-
mock_ledger_client.
|
|
91
|
+
mock_ledger_client.get_strategy_net_deposit.assert_called_once_with(
|
|
90
92
|
wallet_address="0x1234567890123456789012345678901234567890"
|
|
91
93
|
)
|
|
92
94
|
|
|
@@ -98,7 +100,7 @@ class TestLedgerAdapter:
|
|
|
98
100
|
"status": "recorded",
|
|
99
101
|
"timestamp": "2024-01-15T10:30:00Z",
|
|
100
102
|
}
|
|
101
|
-
mock_ledger_client.
|
|
103
|
+
mock_ledger_client.add_strategy_deposit.return_value = mock_response
|
|
102
104
|
|
|
103
105
|
# Test
|
|
104
106
|
success, data = await adapter.record_deposit(
|
|
@@ -112,7 +114,7 @@ class TestLedgerAdapter:
|
|
|
112
114
|
|
|
113
115
|
assert success is True
|
|
114
116
|
assert data == mock_response
|
|
115
|
-
mock_ledger_client.
|
|
117
|
+
mock_ledger_client.add_strategy_deposit.assert_called_once_with(
|
|
116
118
|
wallet_address="0x1234567890123456789012345678901234567890",
|
|
117
119
|
chain_id=8453,
|
|
118
120
|
token_address="0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
@@ -130,7 +132,7 @@ class TestLedgerAdapter:
|
|
|
130
132
|
"status": "recorded",
|
|
131
133
|
"timestamp": "2024-01-15T11:00:00Z",
|
|
132
134
|
}
|
|
133
|
-
mock_ledger_client.
|
|
135
|
+
mock_ledger_client.add_strategy_withdraw.return_value = mock_response
|
|
134
136
|
|
|
135
137
|
# Test
|
|
136
138
|
success, data = await adapter.record_withdrawal(
|
|
@@ -148,21 +150,24 @@ class TestLedgerAdapter:
|
|
|
148
150
|
@pytest.mark.asyncio
|
|
149
151
|
async def test_record_operation_success(self, adapter, mock_ledger_client):
|
|
150
152
|
"""Test successful operation recording"""
|
|
153
|
+
from wayfinder_paths.core.adapters.models import SWAP
|
|
154
|
+
|
|
151
155
|
mock_response = {
|
|
152
156
|
"operation_id": "op_123",
|
|
153
157
|
"status": "recorded",
|
|
154
158
|
"timestamp": "2024-01-15T10:45:00Z",
|
|
155
159
|
}
|
|
156
|
-
mock_ledger_client.
|
|
160
|
+
mock_ledger_client.add_strategy_operation.return_value = mock_response
|
|
157
161
|
|
|
158
162
|
# Test
|
|
159
|
-
operation_data =
|
|
160
|
-
"
|
|
161
|
-
"
|
|
162
|
-
"
|
|
163
|
-
"
|
|
164
|
-
|
|
165
|
-
|
|
163
|
+
operation_data = SWAP(
|
|
164
|
+
from_token_id="0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
165
|
+
to_token_id="0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
|
|
166
|
+
from_amount="1000000000000000000",
|
|
167
|
+
to_amount="995000000000000000",
|
|
168
|
+
from_amount_usd=1000.0,
|
|
169
|
+
to_amount_usd=995.0,
|
|
170
|
+
)
|
|
166
171
|
|
|
167
172
|
success, data = await adapter.record_operation(
|
|
168
173
|
wallet_address="0x1234567890123456789012345678901234567890",
|
|
@@ -184,7 +189,7 @@ class TestLedgerAdapter:
|
|
|
184
189
|
{"operation": "SWAP", "amount": "200000000000000000"},
|
|
185
190
|
]
|
|
186
191
|
}
|
|
187
|
-
mock_ledger_client.
|
|
192
|
+
mock_ledger_client.get_strategy_transactions.return_value = mock_transactions
|
|
188
193
|
|
|
189
194
|
# Test
|
|
190
195
|
success, data = await adapter.get_transaction_summary(
|
|
@@ -55,17 +55,6 @@ else:
|
|
|
55
55
|
print(f"Error: {data}")
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
### Get Combined Pool Reports
|
|
59
|
-
|
|
60
|
-
```python
|
|
61
|
-
success, data = await adapter.get_combined_pool_reports()
|
|
62
|
-
if success:
|
|
63
|
-
reports = data.get("reports", [])
|
|
64
|
-
print(f"Received {len(reports)} combined reports")
|
|
65
|
-
else:
|
|
66
|
-
print(f"Error: {data}")
|
|
67
|
-
```
|
|
68
|
-
|
|
69
58
|
### Find High Yield Pools
|
|
70
59
|
|
|
71
60
|
```python
|
|
@@ -194,7 +183,6 @@ The adapter uses the following Wayfinder API endpoints:
|
|
|
194
183
|
|
|
195
184
|
- `GET /api/v1/public/pools/?pool_ids=X` - Get pools by IDs
|
|
196
185
|
- `GET /api/v1/public/pools/` - Get all pools
|
|
197
|
-
- `GET /api/v1/public/pools/combined/` - Get combined pool reports
|
|
198
186
|
- `GET /api/v1/public/pools/llama/matches/` - Get Llama matches
|
|
199
187
|
- `GET /api/v1/public/pools/llama/reports/` - Get Llama reports
|
|
200
188
|
|
|
@@ -209,7 +197,7 @@ All methods return a tuple of `(success: bool, data: Any)` where:
|
|
|
209
197
|
Run the adapter tests:
|
|
210
198
|
|
|
211
199
|
```bash
|
|
212
|
-
pytest wayfinder_paths/
|
|
200
|
+
pytest wayfinder_paths/adapters/pool_adapter/test_adapter.py -v
|
|
213
201
|
```
|
|
214
202
|
|
|
215
203
|
## Dependencies
|