wayfinder-paths 0.1.7__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 +399 -0
- wayfinder_paths/__init__.py +22 -0
- wayfinder_paths/abis/generic/erc20.json +383 -0
- wayfinder_paths/adapters/__init__.py +0 -0
- wayfinder_paths/adapters/balance_adapter/README.md +94 -0
- wayfinder_paths/adapters/balance_adapter/adapter.py +238 -0
- wayfinder_paths/adapters/balance_adapter/examples.json +6 -0
- wayfinder_paths/adapters/balance_adapter/manifest.yaml +8 -0
- wayfinder_paths/adapters/balance_adapter/test_adapter.py +59 -0
- wayfinder_paths/adapters/brap_adapter/README.md +249 -0
- wayfinder_paths/adapters/brap_adapter/__init__.py +7 -0
- wayfinder_paths/adapters/brap_adapter/adapter.py +726 -0
- wayfinder_paths/adapters/brap_adapter/examples.json +175 -0
- wayfinder_paths/adapters/brap_adapter/manifest.yaml +11 -0
- wayfinder_paths/adapters/brap_adapter/test_adapter.py +286 -0
- wayfinder_paths/adapters/hyperlend_adapter/__init__.py +7 -0
- wayfinder_paths/adapters/hyperlend_adapter/adapter.py +305 -0
- wayfinder_paths/adapters/hyperlend_adapter/manifest.yaml +10 -0
- wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +274 -0
- wayfinder_paths/adapters/hyperliquid_adapter/__init__.py +18 -0
- wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +1093 -0
- wayfinder_paths/adapters/hyperliquid_adapter/executor.py +549 -0
- wayfinder_paths/adapters/hyperliquid_adapter/manifest.yaml +8 -0
- wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +1050 -0
- wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +126 -0
- wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +219 -0
- wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +220 -0
- wayfinder_paths/adapters/hyperliquid_adapter/utils.py +134 -0
- wayfinder_paths/adapters/ledger_adapter/README.md +145 -0
- wayfinder_paths/adapters/ledger_adapter/__init__.py +7 -0
- wayfinder_paths/adapters/ledger_adapter/adapter.py +289 -0
- wayfinder_paths/adapters/ledger_adapter/examples.json +137 -0
- wayfinder_paths/adapters/ledger_adapter/manifest.yaml +11 -0
- wayfinder_paths/adapters/ledger_adapter/test_adapter.py +205 -0
- wayfinder_paths/adapters/pool_adapter/README.md +206 -0
- wayfinder_paths/adapters/pool_adapter/__init__.py +7 -0
- wayfinder_paths/adapters/pool_adapter/adapter.py +282 -0
- wayfinder_paths/adapters/pool_adapter/examples.json +143 -0
- wayfinder_paths/adapters/pool_adapter/manifest.yaml +10 -0
- wayfinder_paths/adapters/pool_adapter/test_adapter.py +220 -0
- wayfinder_paths/adapters/token_adapter/README.md +101 -0
- wayfinder_paths/adapters/token_adapter/__init__.py +3 -0
- wayfinder_paths/adapters/token_adapter/adapter.py +96 -0
- wayfinder_paths/adapters/token_adapter/examples.json +26 -0
- wayfinder_paths/adapters/token_adapter/manifest.yaml +6 -0
- wayfinder_paths/adapters/token_adapter/test_adapter.py +125 -0
- wayfinder_paths/config.example.json +22 -0
- wayfinder_paths/conftest.py +31 -0
- wayfinder_paths/core/__init__.py +18 -0
- wayfinder_paths/core/adapters/BaseAdapter.py +65 -0
- wayfinder_paths/core/adapters/__init__.py +5 -0
- wayfinder_paths/core/adapters/base.py +5 -0
- wayfinder_paths/core/adapters/models.py +46 -0
- wayfinder_paths/core/analytics/__init__.py +11 -0
- wayfinder_paths/core/analytics/bootstrap.py +57 -0
- wayfinder_paths/core/analytics/stats.py +48 -0
- wayfinder_paths/core/analytics/test_analytics.py +170 -0
- wayfinder_paths/core/clients/AuthClient.py +83 -0
- wayfinder_paths/core/clients/BRAPClient.py +109 -0
- wayfinder_paths/core/clients/ClientManager.py +210 -0
- wayfinder_paths/core/clients/HyperlendClient.py +192 -0
- wayfinder_paths/core/clients/LedgerClient.py +443 -0
- wayfinder_paths/core/clients/PoolClient.py +128 -0
- wayfinder_paths/core/clients/SimulationClient.py +192 -0
- wayfinder_paths/core/clients/TokenClient.py +89 -0
- wayfinder_paths/core/clients/TransactionClient.py +63 -0
- wayfinder_paths/core/clients/WalletClient.py +94 -0
- wayfinder_paths/core/clients/WayfinderClient.py +269 -0
- wayfinder_paths/core/clients/__init__.py +48 -0
- wayfinder_paths/core/clients/protocols.py +392 -0
- wayfinder_paths/core/clients/sdk_example.py +110 -0
- wayfinder_paths/core/config.py +458 -0
- wayfinder_paths/core/constants/__init__.py +26 -0
- wayfinder_paths/core/constants/base.py +42 -0
- wayfinder_paths/core/constants/erc20_abi.py +118 -0
- wayfinder_paths/core/constants/hyperlend_abi.py +152 -0
- wayfinder_paths/core/engine/StrategyJob.py +188 -0
- wayfinder_paths/core/engine/__init__.py +5 -0
- wayfinder_paths/core/engine/manifest.py +97 -0
- wayfinder_paths/core/services/__init__.py +0 -0
- wayfinder_paths/core/services/base.py +179 -0
- wayfinder_paths/core/services/local_evm_txn.py +430 -0
- wayfinder_paths/core/services/local_token_txn.py +231 -0
- wayfinder_paths/core/services/web3_service.py +45 -0
- wayfinder_paths/core/settings.py +61 -0
- wayfinder_paths/core/strategies/Strategy.py +280 -0
- wayfinder_paths/core/strategies/__init__.py +5 -0
- wayfinder_paths/core/strategies/base.py +7 -0
- wayfinder_paths/core/strategies/descriptors.py +81 -0
- wayfinder_paths/core/utils/__init__.py +1 -0
- wayfinder_paths/core/utils/evm_helpers.py +206 -0
- wayfinder_paths/core/utils/wallets.py +77 -0
- wayfinder_paths/core/wallets/README.md +91 -0
- wayfinder_paths/core/wallets/WalletManager.py +56 -0
- wayfinder_paths/core/wallets/__init__.py +7 -0
- wayfinder_paths/policies/enso.py +17 -0
- wayfinder_paths/policies/erc20.py +34 -0
- wayfinder_paths/policies/evm.py +21 -0
- wayfinder_paths/policies/hyper_evm.py +19 -0
- wayfinder_paths/policies/hyperlend.py +12 -0
- wayfinder_paths/policies/hyperliquid.py +30 -0
- wayfinder_paths/policies/moonwell.py +54 -0
- wayfinder_paths/policies/prjx.py +30 -0
- wayfinder_paths/policies/util.py +27 -0
- wayfinder_paths/run_strategy.py +411 -0
- wayfinder_paths/scripts/__init__.py +0 -0
- wayfinder_paths/scripts/create_strategy.py +181 -0
- wayfinder_paths/scripts/make_wallets.py +169 -0
- wayfinder_paths/scripts/run_strategy.py +124 -0
- wayfinder_paths/scripts/validate_manifests.py +213 -0
- wayfinder_paths/strategies/__init__.py +0 -0
- wayfinder_paths/strategies/basis_trading_strategy/README.md +213 -0
- wayfinder_paths/strategies/basis_trading_strategy/__init__.py +3 -0
- wayfinder_paths/strategies/basis_trading_strategy/constants.py +1 -0
- wayfinder_paths/strategies/basis_trading_strategy/examples.json +16 -0
- wayfinder_paths/strategies/basis_trading_strategy/manifest.yaml +23 -0
- wayfinder_paths/strategies/basis_trading_strategy/snapshot_mixin.py +1011 -0
- wayfinder_paths/strategies/basis_trading_strategy/strategy.py +4522 -0
- wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +727 -0
- wayfinder_paths/strategies/basis_trading_strategy/types.py +39 -0
- wayfinder_paths/strategies/config.py +85 -0
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md +100 -0
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/examples.json +8 -0
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/manifest.yaml +7 -0
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +2270 -0
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +352 -0
- wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +96 -0
- wayfinder_paths/strategies/stablecoin_yield_strategy/examples.json +17 -0
- wayfinder_paths/strategies/stablecoin_yield_strategy/manifest.yaml +17 -0
- wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +1810 -0
- wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +520 -0
- wayfinder_paths/templates/adapter/README.md +105 -0
- wayfinder_paths/templates/adapter/adapter.py +26 -0
- wayfinder_paths/templates/adapter/examples.json +8 -0
- wayfinder_paths/templates/adapter/manifest.yaml +6 -0
- wayfinder_paths/templates/adapter/test_adapter.py +49 -0
- wayfinder_paths/templates/strategy/README.md +153 -0
- wayfinder_paths/templates/strategy/examples.json +11 -0
- wayfinder_paths/templates/strategy/manifest.yaml +8 -0
- wayfinder_paths/templates/strategy/strategy.py +57 -0
- wayfinder_paths/templates/strategy/test_strategy.py +197 -0
- wayfinder_paths/tests/__init__.py +0 -0
- wayfinder_paths/tests/test_smoke_manifest.py +48 -0
- wayfinder_paths/tests/test_test_coverage.py +212 -0
- wayfinder_paths/tests/test_utils.py +64 -0
- wayfinder_paths-0.1.7.dist-info/LICENSE +21 -0
- wayfinder_paths-0.1.7.dist-info/METADATA +777 -0
- wayfinder_paths-0.1.7.dist-info/RECORD +149 -0
- wayfinder_paths-0.1.7.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Ledger Adapter
|
|
2
|
+
|
|
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
|
+
|
|
5
|
+
## Capabilities
|
|
6
|
+
|
|
7
|
+
- `ledger.read`: Read strategy transaction data and net deposits
|
|
8
|
+
- `ledger.write`: Record deposits, withdrawals, and operations
|
|
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
|
+
|
|
14
|
+
## Configuration
|
|
15
|
+
|
|
16
|
+
The adapter uses the LedgerClient which automatically handles authentication and API configuration through the Wayfinder settings. No additional configuration is required.
|
|
17
|
+
|
|
18
|
+
The LedgerClient will automatically:
|
|
19
|
+
- Use the WAYFINDER_API_URL from settings
|
|
20
|
+
- Handle authentication via environment variables or config.json
|
|
21
|
+
- Manage token refresh and retry logic
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
### Initialize the Adapter
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from wayfinder_paths.adapters.ledger_adapter.adapter import LedgerAdapter
|
|
29
|
+
|
|
30
|
+
# No configuration needed - uses LedgerClient with automatic settings
|
|
31
|
+
adapter = LedgerAdapter()
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Get Strategy Transaction History
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
success, data = await adapter.get_strategy_transactions(
|
|
38
|
+
wallet_address="0x1234567890123456789012345678901234567890",
|
|
39
|
+
limit=10,
|
|
40
|
+
offset=0
|
|
41
|
+
)
|
|
42
|
+
if success:
|
|
43
|
+
transactions = data.get("transactions", [])
|
|
44
|
+
print(f"Found {len(transactions)} transactions")
|
|
45
|
+
else:
|
|
46
|
+
print(f"Error: {data}")
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Get Net Deposit Amount
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
success, data = await adapter.get_strategy_net_deposit(
|
|
53
|
+
wallet_address="0x1234567890123456789012345678901234567890"
|
|
54
|
+
)
|
|
55
|
+
if success:
|
|
56
|
+
net_deposit = data.get("net_deposit", 0)
|
|
57
|
+
print(f"Net deposit: {net_deposit} USDC")
|
|
58
|
+
else:
|
|
59
|
+
print(f"Error: {data}")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Record a Deposit
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
success, data = await adapter.record_deposit(
|
|
66
|
+
wallet_address="0x1234567890123456789012345678901234567890",
|
|
67
|
+
chain_id=8453,
|
|
68
|
+
token_address="0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
69
|
+
token_amount="1000000000000000000",
|
|
70
|
+
usd_value="1000.00",
|
|
71
|
+
strategy_name="StablecoinYieldStrategy"
|
|
72
|
+
)
|
|
73
|
+
if success:
|
|
74
|
+
print(f"Deposit recorded: {data.get('transaction_id')}")
|
|
75
|
+
else:
|
|
76
|
+
print(f"Error: {data}")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Record a Withdrawal
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
success, data = await adapter.record_withdrawal(
|
|
83
|
+
wallet_address="0x1234567890123456789012345678901234567890",
|
|
84
|
+
chain_id=8453,
|
|
85
|
+
token_address="0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
86
|
+
token_amount="500000000000000000",
|
|
87
|
+
usd_value="500.00",
|
|
88
|
+
strategy_name="StablecoinYieldStrategy"
|
|
89
|
+
)
|
|
90
|
+
if success:
|
|
91
|
+
print(f"Withdrawal recorded: {data.get('transaction_id')}")
|
|
92
|
+
else:
|
|
93
|
+
print(f"Error: {data}")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Record an Operation
|
|
97
|
+
|
|
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
|
+
|
|
110
|
+
success, op = await adapter.record_operation(
|
|
111
|
+
wallet_address=strategy_address,
|
|
112
|
+
operation_data=operation,
|
|
113
|
+
usd_value="1000.00",
|
|
114
|
+
strategy_name="StablecoinYieldStrategy",
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Latest Transactions and Summaries
|
|
120
|
+
|
|
121
|
+
```python
|
|
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)
|
|
124
|
+
if success:
|
|
125
|
+
print(f"Total transactions: {summary.get('total_transactions')}")
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Error Handling
|
|
129
|
+
|
|
130
|
+
All methods return a tuple of `(success: bool, data: Any)` where:
|
|
131
|
+
- `success` is `True` if the operation succeeded
|
|
132
|
+
- `data` contains the response data on success or error message on failure
|
|
133
|
+
|
|
134
|
+
## Testing
|
|
135
|
+
|
|
136
|
+
Run the adapter tests:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
pytest wayfinder_paths/adapters/ledger_adapter/test_adapter.py -v
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Dependencies
|
|
143
|
+
|
|
144
|
+
- `LedgerClient` - Low-level API client for ledger operations
|
|
145
|
+
- `BaseAdapter` - Base adapter class with common functionality
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
|
|
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
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class LedgerAdapter(BaseAdapter):
|
|
15
|
+
"""
|
|
16
|
+
Ledger adapter for strategy transaction history and bookkeeping operations.
|
|
17
|
+
|
|
18
|
+
Provides high-level operations for:
|
|
19
|
+
- Fetching strategy transaction history
|
|
20
|
+
- Getting net deposit amounts
|
|
21
|
+
- Getting last rotation time
|
|
22
|
+
- Recording deposits, withdrawals, and operations
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
adapter_type: str = "LEDGER"
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
config: dict[str, Any] | None = None,
|
|
30
|
+
ledger_client: LedgerClient | None = None,
|
|
31
|
+
):
|
|
32
|
+
super().__init__("ledger_adapter", config)
|
|
33
|
+
self.ledger_client = ledger_client or LedgerClient()
|
|
34
|
+
|
|
35
|
+
async def get_strategy_transactions(
|
|
36
|
+
self, wallet_address: str, limit: int = 50, offset: int = 0
|
|
37
|
+
) -> tuple[bool, StrategyTransactionList | str]:
|
|
38
|
+
"""
|
|
39
|
+
Get paginated strategy transaction history.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
wallet_address: Strategy wallet address
|
|
43
|
+
limit: Maximum number of transactions to return
|
|
44
|
+
offset: Number of transactions to skip
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Tuple of (success, data) where data is transaction list or error message
|
|
48
|
+
"""
|
|
49
|
+
try:
|
|
50
|
+
data = await self.ledger_client.get_strategy_transactions(
|
|
51
|
+
wallet_address=wallet_address, limit=limit, offset=offset
|
|
52
|
+
)
|
|
53
|
+
return (True, data)
|
|
54
|
+
except Exception as e:
|
|
55
|
+
self.logger.error(f"Error fetching strategy transactions: {e}")
|
|
56
|
+
return (False, str(e))
|
|
57
|
+
|
|
58
|
+
async def get_strategy_net_deposit(
|
|
59
|
+
self, wallet_address: str
|
|
60
|
+
) -> tuple[bool, NetDeposit | str]:
|
|
61
|
+
"""
|
|
62
|
+
Get net deposit amount (deposits - withdrawals) for a strategy.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
wallet_address: Strategy wallet address
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Tuple of (success, data) where data contains net_deposit or error message
|
|
69
|
+
"""
|
|
70
|
+
try:
|
|
71
|
+
data = await self.ledger_client.get_strategy_net_deposit(
|
|
72
|
+
wallet_address=wallet_address
|
|
73
|
+
)
|
|
74
|
+
return (True, data)
|
|
75
|
+
except Exception as e:
|
|
76
|
+
self.logger.error(f"Error fetching strategy net deposit: {e}")
|
|
77
|
+
return (False, str(e))
|
|
78
|
+
|
|
79
|
+
async def get_strategy_latest_transactions(
|
|
80
|
+
self, wallet_address: str
|
|
81
|
+
) -> tuple[bool, StrategyTransactionList | str]:
|
|
82
|
+
"""
|
|
83
|
+
Get the latest transactions for a strategy.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
wallet_address: Strategy wallet address
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Tuple of (success, data) where data contains latest transactions or error message
|
|
90
|
+
"""
|
|
91
|
+
try:
|
|
92
|
+
data = await self.ledger_client.get_strategy_latest_transactions(
|
|
93
|
+
wallet_address=wallet_address
|
|
94
|
+
)
|
|
95
|
+
return (True, data)
|
|
96
|
+
except Exception as e:
|
|
97
|
+
self.logger.error(f"Error fetching strategy last transactions: {e}")
|
|
98
|
+
return (False, str(e))
|
|
99
|
+
|
|
100
|
+
async def record_deposit(
|
|
101
|
+
self,
|
|
102
|
+
wallet_address: str,
|
|
103
|
+
chain_id: int,
|
|
104
|
+
token_address: str,
|
|
105
|
+
token_amount: str | float,
|
|
106
|
+
usd_value: str | float,
|
|
107
|
+
data: dict[str, Any] | None = None,
|
|
108
|
+
strategy_name: str | None = None,
|
|
109
|
+
) -> tuple[bool, TransactionRecord | str]:
|
|
110
|
+
"""
|
|
111
|
+
Record a strategy deposit transaction.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
wallet_address: Strategy wallet address
|
|
115
|
+
chain_id: Blockchain chain ID
|
|
116
|
+
token_address: Token contract address
|
|
117
|
+
token_amount: Amount deposited (in token units)
|
|
118
|
+
usd_value: USD value of the deposit
|
|
119
|
+
data: Additional transaction data
|
|
120
|
+
strategy_name: Name of the strategy making the deposit
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Tuple of (success, data) where data is transaction record or error message
|
|
124
|
+
"""
|
|
125
|
+
try:
|
|
126
|
+
result = await self.ledger_client.add_strategy_deposit(
|
|
127
|
+
wallet_address=wallet_address,
|
|
128
|
+
chain_id=chain_id,
|
|
129
|
+
token_address=token_address,
|
|
130
|
+
token_amount=token_amount,
|
|
131
|
+
usd_value=usd_value,
|
|
132
|
+
data=data,
|
|
133
|
+
strategy_name=strategy_name,
|
|
134
|
+
)
|
|
135
|
+
return (True, result)
|
|
136
|
+
except Exception as e:
|
|
137
|
+
self.logger.error(f"Error recording deposit: {e}")
|
|
138
|
+
return (False, str(e))
|
|
139
|
+
|
|
140
|
+
async def record_withdrawal(
|
|
141
|
+
self,
|
|
142
|
+
wallet_address: str,
|
|
143
|
+
chain_id: int,
|
|
144
|
+
token_address: str,
|
|
145
|
+
token_amount: str | float,
|
|
146
|
+
usd_value: str | float,
|
|
147
|
+
data: dict[str, Any] | None = None,
|
|
148
|
+
strategy_name: str | None = None,
|
|
149
|
+
) -> tuple[bool, TransactionRecord | str]:
|
|
150
|
+
"""
|
|
151
|
+
Record a strategy withdrawal transaction.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
wallet_address: Strategy wallet address
|
|
155
|
+
chain_id: Blockchain chain ID
|
|
156
|
+
token_address: Token contract address
|
|
157
|
+
token_amount: Amount withdrawn (in token units)
|
|
158
|
+
usd_value: USD value of the withdrawal
|
|
159
|
+
data: Additional transaction data
|
|
160
|
+
strategy_name: Name of the strategy making the withdrawal
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
Tuple of (success, data) where data is transaction record or error message
|
|
164
|
+
"""
|
|
165
|
+
try:
|
|
166
|
+
result = await self.ledger_client.add_strategy_withdraw(
|
|
167
|
+
wallet_address=wallet_address,
|
|
168
|
+
chain_id=chain_id,
|
|
169
|
+
token_address=token_address,
|
|
170
|
+
token_amount=token_amount,
|
|
171
|
+
usd_value=usd_value,
|
|
172
|
+
data=data,
|
|
173
|
+
strategy_name=strategy_name,
|
|
174
|
+
)
|
|
175
|
+
return (True, result)
|
|
176
|
+
except Exception as e:
|
|
177
|
+
self.logger.error(f"Error recording withdrawal: {e}")
|
|
178
|
+
return (False, str(e))
|
|
179
|
+
|
|
180
|
+
async def record_operation(
|
|
181
|
+
self,
|
|
182
|
+
wallet_address: str,
|
|
183
|
+
operation_data: Operation,
|
|
184
|
+
usd_value: str | float,
|
|
185
|
+
strategy_name: str | None = None,
|
|
186
|
+
) -> tuple[bool, TransactionRecord | str]:
|
|
187
|
+
"""
|
|
188
|
+
Record a strategy operation (e.g., swaps, rebalances) for bookkeeping.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
wallet_address: Strategy wallet address
|
|
192
|
+
operation_data: Operation model (SWAP, LEND, BORROW, etc.)
|
|
193
|
+
usd_value: USD value of the operation
|
|
194
|
+
strategy_name: Name of the strategy performing the operation
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
Tuple of (success, data) where data is operation record or error message
|
|
198
|
+
"""
|
|
199
|
+
try:
|
|
200
|
+
result = await self.ledger_client.add_strategy_operation(
|
|
201
|
+
wallet_address=wallet_address,
|
|
202
|
+
operation_data=operation_data,
|
|
203
|
+
usd_value=usd_value,
|
|
204
|
+
strategy_name=strategy_name,
|
|
205
|
+
)
|
|
206
|
+
return (True, result)
|
|
207
|
+
except Exception as e:
|
|
208
|
+
self.logger.error(f"Error recording operation: {e}")
|
|
209
|
+
return (False, str(e))
|
|
210
|
+
|
|
211
|
+
async def get_transaction_summary(
|
|
212
|
+
self, wallet_address: str, limit: int = 10
|
|
213
|
+
) -> tuple[bool, Any]:
|
|
214
|
+
"""
|
|
215
|
+
Get a summary of recent strategy transactions.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
wallet_address: Strategy wallet address
|
|
219
|
+
limit: Number of recent transactions to include
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Tuple of (success, data) where data is transaction summary or error message
|
|
223
|
+
"""
|
|
224
|
+
try:
|
|
225
|
+
success, transactions_data = await self.get_strategy_transactions(
|
|
226
|
+
wallet_address=wallet_address, limit=limit
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
if not success:
|
|
230
|
+
return (False, transactions_data)
|
|
231
|
+
|
|
232
|
+
transactions = transactions_data.get("transactions", [])
|
|
233
|
+
|
|
234
|
+
# Create summary
|
|
235
|
+
summary = {
|
|
236
|
+
"total_transactions": len(transactions),
|
|
237
|
+
"recent_transactions": transactions[:limit],
|
|
238
|
+
"operations": {
|
|
239
|
+
"deposits": len(
|
|
240
|
+
[t for t in transactions if t.get("operation") == "DEPOSIT"]
|
|
241
|
+
),
|
|
242
|
+
"withdrawals": len(
|
|
243
|
+
[t for t in transactions if t.get("operation") == "WITHDRAW"]
|
|
244
|
+
),
|
|
245
|
+
"operations": len(
|
|
246
|
+
[
|
|
247
|
+
t
|
|
248
|
+
for t in transactions
|
|
249
|
+
if t.get("operation") not in ["DEPOSIT", "WITHDRAW"]
|
|
250
|
+
]
|
|
251
|
+
),
|
|
252
|
+
},
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return (True, summary)
|
|
256
|
+
except Exception as e:
|
|
257
|
+
self.logger.error(f"Error creating transaction summary: {e}")
|
|
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))
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
{
|
|
2
|
+
"get_vault_transactions": {
|
|
3
|
+
"description": "Get vault transaction history",
|
|
4
|
+
"input": {
|
|
5
|
+
"wallet_address": "0x1234567890123456789012345678901234567890",
|
|
6
|
+
"limit": 10,
|
|
7
|
+
"offset": 0
|
|
8
|
+
},
|
|
9
|
+
"output": {
|
|
10
|
+
"success": true,
|
|
11
|
+
"data": {
|
|
12
|
+
"transactions": [
|
|
13
|
+
{
|
|
14
|
+
"id": "tx_123",
|
|
15
|
+
"operation": "DEPOSIT",
|
|
16
|
+
"timestamp": "2024-01-15T10:30:00Z",
|
|
17
|
+
"amount": "1000000000000000000",
|
|
18
|
+
"token_address": "0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
19
|
+
"usd_value": "1000.00",
|
|
20
|
+
"strategy_name": "StablecoinYieldStrategy"
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"total": 1,
|
|
24
|
+
"limit": 10,
|
|
25
|
+
"offset": 0
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"get_vault_net_deposit": {
|
|
30
|
+
"description": "Get net deposit amount for a vault",
|
|
31
|
+
"input": {
|
|
32
|
+
"wallet_address": "0x1234567890123456789012345678901234567890"
|
|
33
|
+
},
|
|
34
|
+
"output": {
|
|
35
|
+
"success": true,
|
|
36
|
+
"data": {
|
|
37
|
+
"net_deposit": "1000.00",
|
|
38
|
+
"total_deposits": "1500.00",
|
|
39
|
+
"total_withdrawals": "500.00"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"record_deposit": {
|
|
44
|
+
"description": "Record a vault deposit",
|
|
45
|
+
"input": {
|
|
46
|
+
"wallet_address": "0x1234567890123456789012345678901234567890",
|
|
47
|
+
"chain_id": 8453,
|
|
48
|
+
"token_address": "0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
49
|
+
"token_amount": "1000000000000000000",
|
|
50
|
+
"usd_value": "1000.00",
|
|
51
|
+
"strategy_name": "StablecoinYieldStrategy"
|
|
52
|
+
},
|
|
53
|
+
"output": {
|
|
54
|
+
"success": true,
|
|
55
|
+
"data": {
|
|
56
|
+
"transaction_id": "tx_456",
|
|
57
|
+
"status": "recorded",
|
|
58
|
+
"timestamp": "2024-01-15T10:30:00Z"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"record_withdrawal": {
|
|
63
|
+
"description": "Record a vault withdrawal",
|
|
64
|
+
"input": {
|
|
65
|
+
"wallet_address": "0x1234567890123456789012345678901234567890",
|
|
66
|
+
"chain_id": 8453,
|
|
67
|
+
"token_address": "0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
|
|
68
|
+
"token_amount": "500000000000000000",
|
|
69
|
+
"usd_value": "500.00",
|
|
70
|
+
"strategy_name": "StablecoinYieldStrategy"
|
|
71
|
+
},
|
|
72
|
+
"output": {
|
|
73
|
+
"success": true,
|
|
74
|
+
"data": {
|
|
75
|
+
"transaction_id": "tx_789",
|
|
76
|
+
"status": "recorded",
|
|
77
|
+
"timestamp": "2024-01-15T11:00:00Z"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"record_operation": {
|
|
82
|
+
"description": "Record a vault operation (swap, rebalance, etc.)",
|
|
83
|
+
"note": "operation_data must be a Pydantic Operation model (currently only SWAP is implemented)",
|
|
84
|
+
"input": {
|
|
85
|
+
"wallet_address": "0x1234567890123456789012345678901234567890",
|
|
86
|
+
"operation_data": {
|
|
87
|
+
"type": "SWAP",
|
|
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
|
|
97
|
+
},
|
|
98
|
+
"usd_value": "1000.00",
|
|
99
|
+
"strategy_name": "StablecoinYieldStrategy"
|
|
100
|
+
},
|
|
101
|
+
"output": {
|
|
102
|
+
"success": true,
|
|
103
|
+
"data": {
|
|
104
|
+
"operation_id": "op_123",
|
|
105
|
+
"status": "recorded",
|
|
106
|
+
"timestamp": "2024-01-15T10:45:00Z"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
"get_transaction_summary": {
|
|
111
|
+
"description": "Get a summary of recent vault transactions",
|
|
112
|
+
"input": {
|
|
113
|
+
"wallet_address": "0x1234567890123456789012345678901234567890",
|
|
114
|
+
"limit": 5
|
|
115
|
+
},
|
|
116
|
+
"output": {
|
|
117
|
+
"success": true,
|
|
118
|
+
"data": {
|
|
119
|
+
"total_transactions": 3,
|
|
120
|
+
"recent_transactions": [
|
|
121
|
+
{
|
|
122
|
+
"id": "tx_123",
|
|
123
|
+
"operation": "DEPOSIT",
|
|
124
|
+
"timestamp": "2024-01-15T10:30:00Z",
|
|
125
|
+
"amount": "1000000000000000000",
|
|
126
|
+
"usd_value": "1000.00"
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
"operations": {
|
|
130
|
+
"deposits": 1,
|
|
131
|
+
"withdrawals": 1,
|
|
132
|
+
"operations": 1
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
schema_version: "0.1"
|
|
2
|
+
entrypoint: "adapters.ledger_adapter.adapter.LedgerAdapter"
|
|
3
|
+
capabilities:
|
|
4
|
+
- "ledger.read"
|
|
5
|
+
- "ledger.write"
|
|
6
|
+
- "strategy.transactions"
|
|
7
|
+
- "strategy.deposits"
|
|
8
|
+
- "strategy.withdrawals"
|
|
9
|
+
- "strategy.operations"
|
|
10
|
+
dependencies:
|
|
11
|
+
- "LedgerClient"
|