wayfinder-paths 0.1.3__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.

Files changed (109) hide show
  1. wayfinder_paths/CONFIG_GUIDE.md +37 -32
  2. wayfinder_paths/__init__.py +3 -3
  3. wayfinder_paths/{vaults/adapters → adapters}/balance_adapter/README.md +12 -12
  4. wayfinder_paths/{vaults/adapters → adapters}/balance_adapter/adapter.py +12 -11
  5. wayfinder_paths/{vaults/adapters → adapters}/balance_adapter/examples.json +1 -1
  6. wayfinder_paths/{vaults/adapters → adapters}/balance_adapter/manifest.yaml +1 -1
  7. wayfinder_paths/{vaults/adapters → adapters}/balance_adapter/test_adapter.py +12 -6
  8. wayfinder_paths/{vaults/adapters → adapters}/brap_adapter/README.md +2 -2
  9. wayfinder_paths/{vaults/adapters → adapters}/brap_adapter/adapter.py +30 -23
  10. wayfinder_paths/{vaults/adapters → adapters}/brap_adapter/manifest.yaml +1 -1
  11. wayfinder_paths/{vaults/adapters → adapters}/brap_adapter/test_adapter.py +2 -2
  12. wayfinder_paths/adapters/hyperlend_adapter/__init__.py +7 -0
  13. wayfinder_paths/{vaults/adapters → adapters}/hyperlend_adapter/adapter.py +33 -26
  14. wayfinder_paths/{vaults/adapters → adapters}/hyperlend_adapter/manifest.yaml +1 -1
  15. wayfinder_paths/{vaults/adapters → adapters}/hyperlend_adapter/test_adapter.py +2 -2
  16. wayfinder_paths/{vaults/adapters → adapters}/ledger_adapter/README.md +27 -40
  17. wayfinder_paths/{vaults/adapters → adapters}/ledger_adapter/adapter.py +78 -75
  18. wayfinder_paths/{vaults/adapters → adapters}/ledger_adapter/examples.json +10 -4
  19. wayfinder_paths/adapters/ledger_adapter/manifest.yaml +11 -0
  20. wayfinder_paths/{vaults/adapters → adapters}/ledger_adapter/test_adapter.py +33 -28
  21. wayfinder_paths/{vaults/adapters → adapters}/pool_adapter/README.md +2 -14
  22. wayfinder_paths/{vaults/adapters → adapters}/pool_adapter/adapter.py +12 -19
  23. wayfinder_paths/{vaults/adapters → adapters}/pool_adapter/manifest.yaml +1 -1
  24. wayfinder_paths/{vaults/adapters → adapters}/pool_adapter/test_adapter.py +2 -2
  25. wayfinder_paths/{vaults/adapters → adapters}/token_adapter/README.md +1 -1
  26. wayfinder_paths/{vaults/adapters → adapters}/token_adapter/adapter.py +8 -4
  27. wayfinder_paths/adapters/token_adapter/examples.json +26 -0
  28. wayfinder_paths/{vaults/adapters → adapters}/token_adapter/manifest.yaml +1 -1
  29. wayfinder_paths/{vaults/adapters → adapters}/token_adapter/test_adapter.py +1 -1
  30. wayfinder_paths/config.example.json +3 -1
  31. wayfinder_paths/core/__init__.py +3 -3
  32. wayfinder_paths/core/adapters/BaseAdapter.py +20 -3
  33. wayfinder_paths/core/adapters/models.py +41 -0
  34. wayfinder_paths/core/clients/BRAPClient.py +21 -2
  35. wayfinder_paths/core/clients/ClientManager.py +42 -63
  36. wayfinder_paths/core/clients/HyperlendClient.py +46 -5
  37. wayfinder_paths/core/clients/LedgerClient.py +350 -124
  38. wayfinder_paths/core/clients/PoolClient.py +51 -19
  39. wayfinder_paths/core/clients/SimulationClient.py +16 -4
  40. wayfinder_paths/core/clients/TokenClient.py +34 -18
  41. wayfinder_paths/core/clients/TransactionClient.py +18 -2
  42. wayfinder_paths/core/clients/WalletClient.py +35 -4
  43. wayfinder_paths/core/clients/WayfinderClient.py +16 -5
  44. wayfinder_paths/core/clients/protocols.py +69 -62
  45. wayfinder_paths/core/clients/sdk_example.py +0 -5
  46. wayfinder_paths/core/config.py +192 -103
  47. wayfinder_paths/core/constants/base.py +17 -0
  48. wayfinder_paths/core/engine/{VaultJob.py → StrategyJob.py} +25 -19
  49. wayfinder_paths/core/engine/__init__.py +2 -2
  50. wayfinder_paths/core/engine/manifest.py +1 -1
  51. wayfinder_paths/core/services/base.py +6 -4
  52. wayfinder_paths/core/services/local_evm_txn.py +3 -2
  53. wayfinder_paths/core/settings.py +2 -2
  54. wayfinder_paths/core/strategies/Strategy.py +123 -37
  55. wayfinder_paths/core/utils/evm_helpers.py +12 -10
  56. wayfinder_paths/core/wallets/README.md +3 -3
  57. wayfinder_paths/core/wallets/WalletManager.py +3 -3
  58. wayfinder_paths/{vaults/policies → policies}/enso.py +1 -1
  59. wayfinder_paths/{vaults/policies → policies}/hyper_evm.py +2 -2
  60. wayfinder_paths/{vaults/policies → policies}/hyperlend.py +1 -1
  61. wayfinder_paths/{vaults/policies → policies}/moonwell.py +1 -1
  62. wayfinder_paths/{vaults/policies → policies}/prjx.py +1 -1
  63. wayfinder_paths/run_strategy.py +29 -27
  64. wayfinder_paths/scripts/create_strategy.py +3 -3
  65. wayfinder_paths/scripts/make_wallets.py +6 -6
  66. wayfinder_paths/scripts/validate_manifests.py +2 -2
  67. wayfinder_paths/{vaults/strategies → strategies}/hyperlend_stable_yield_strategy/README.md +10 -9
  68. wayfinder_paths/{vaults/strategies → strategies}/hyperlend_stable_yield_strategy/manifest.yaml +1 -1
  69. wayfinder_paths/{vaults/strategies → strategies}/hyperlend_stable_yield_strategy/strategy.py +47 -167
  70. wayfinder_paths/{vaults/strategies → strategies}/hyperlend_stable_yield_strategy/test_strategy.py +10 -8
  71. wayfinder_paths/{vaults/strategies → strategies}/stablecoin_yield_strategy/README.md +15 -14
  72. wayfinder_paths/{vaults/strategies → strategies}/stablecoin_yield_strategy/manifest.yaml +2 -2
  73. wayfinder_paths/{vaults/strategies → strategies}/stablecoin_yield_strategy/strategy.py +97 -97
  74. wayfinder_paths/{vaults/strategies → strategies}/stablecoin_yield_strategy/test_strategy.py +8 -8
  75. wayfinder_paths/{vaults/templates → templates}/adapter/README.md +5 -5
  76. wayfinder_paths/{vaults/templates → templates}/adapter/manifest.yaml +1 -1
  77. wayfinder_paths/{vaults/templates → templates}/adapter/test_adapter.py +1 -1
  78. wayfinder_paths/{vaults/templates → templates}/strategy/README.md +10 -9
  79. wayfinder_paths/{vaults/templates → templates}/strategy/manifest.yaml +1 -1
  80. wayfinder_paths/{vaults/templates → templates}/strategy/test_strategy.py +8 -8
  81. wayfinder_paths/tests/test_test_coverage.py +5 -5
  82. {wayfinder_paths-0.1.3.dist-info → wayfinder_paths-0.1.5.dist-info}/METADATA +146 -69
  83. wayfinder_paths-0.1.5.dist-info/RECORD +126 -0
  84. wayfinder_paths/vaults/adapters/hyperlend_adapter/__init__.py +0 -7
  85. wayfinder_paths/vaults/adapters/ledger_adapter/manifest.yaml +0 -11
  86. wayfinder_paths/vaults/adapters/token_adapter/examples.json +0 -26
  87. wayfinder_paths/vaults/strategies/__init__.py +0 -0
  88. wayfinder_paths-0.1.3.dist-info/RECORD +0 -126
  89. /wayfinder_paths/{vaults → adapters}/__init__.py +0 -0
  90. /wayfinder_paths/{vaults/adapters → adapters}/brap_adapter/__init__.py +0 -0
  91. /wayfinder_paths/{vaults/adapters → adapters}/brap_adapter/examples.json +0 -0
  92. /wayfinder_paths/{vaults/adapters → adapters}/ledger_adapter/__init__.py +0 -0
  93. /wayfinder_paths/{vaults/adapters → adapters}/pool_adapter/__init__.py +0 -0
  94. /wayfinder_paths/{vaults/adapters → adapters}/pool_adapter/examples.json +0 -0
  95. /wayfinder_paths/{vaults/adapters → adapters}/token_adapter/__init__.py +0 -0
  96. /wayfinder_paths/{vaults/policies → policies}/erc20.py +0 -0
  97. /wayfinder_paths/{vaults/policies → policies}/evm.py +0 -0
  98. /wayfinder_paths/{vaults/policies → policies}/hyperliquid.py +0 -0
  99. /wayfinder_paths/{vaults/policies → policies}/util.py +0 -0
  100. /wayfinder_paths/{vaults/adapters → strategies}/__init__.py +0 -0
  101. /wayfinder_paths/{vaults/strategies → strategies}/config.py +0 -0
  102. /wayfinder_paths/{vaults/strategies → strategies}/hyperlend_stable_yield_strategy/examples.json +0 -0
  103. /wayfinder_paths/{vaults/strategies → strategies}/stablecoin_yield_strategy/examples.json +0 -0
  104. /wayfinder_paths/{vaults/templates → templates}/adapter/adapter.py +0 -0
  105. /wayfinder_paths/{vaults/templates → templates}/adapter/examples.json +0 -0
  106. /wayfinder_paths/{vaults/templates → templates}/strategy/examples.json +0 -0
  107. /wayfinder_paths/{vaults/templates → templates}/strategy/strategy.py +0 -0
  108. {wayfinder_paths-0.1.3.dist-info → wayfinder_paths-0.1.5.dist-info}/LICENSE +0 -0
  109. {wayfinder_paths-0.1.3.dist-info → wayfinder_paths-0.1.5.dist-info}/WHEEL +0 -0
@@ -2,7 +2,7 @@ from unittest.mock import AsyncMock, patch
2
2
 
3
3
  import pytest
4
4
 
5
- from wayfinder_paths.vaults.adapters.ledger_adapter.adapter import LedgerAdapter
5
+ from wayfinder_paths.adapters.ledger_adapter.adapter import LedgerAdapter
6
6
 
7
7
 
8
8
  class TestLedgerAdapter:
@@ -18,14 +18,14 @@ class TestLedgerAdapter:
18
18
  def adapter(self, mock_ledger_client):
19
19
  """Create a LedgerAdapter instance with mocked client for testing"""
20
20
  with patch(
21
- "vaults.adapters.ledger_adapter.adapter.LedgerClient",
21
+ "adapters.ledger_adapter.adapter.LedgerClient",
22
22
  return_value=mock_ledger_client,
23
23
  ):
24
24
  return LedgerAdapter()
25
25
 
26
26
  @pytest.mark.asyncio
27
- async def test_get_vault_transactions_success(self, adapter, mock_ledger_client):
28
- """Test successful vault transaction retrieval"""
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.get_vault_transactions = AsyncMock(
40
+ mock_ledger_client.get_strategy_transactions = AsyncMock(
41
41
  return_value=mock_response
42
42
  )
43
43
 
44
- success, data = await adapter.get_vault_transactions(
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.get_vault_transactions.assert_called_once_with(
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 test_get_vault_transactions_failure(self, adapter, mock_ledger_client):
60
- """Test vault transaction retrieval failure"""
61
- mock_ledger_client.get_vault_transactions = AsyncMock(
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.get_vault_transactions(
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 test_get_vault_net_deposit_success(self, adapter, mock_ledger_client):
74
- """Test successful vault net deposit retrieval"""
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.get_vault_net_deposit = AsyncMock(return_value=mock_response)
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.get_vault_net_deposit(
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.get_vault_net_deposit.assert_called_once_with(
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.add_vault_deposit.return_value = mock_response
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.add_vault_deposit.assert_called_once_with(
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.add_vault_withdraw.return_value = mock_response
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.add_vault_operation.return_value = mock_response
160
+ mock_ledger_client.add_strategy_operation.return_value = mock_response
157
161
 
158
162
  # Test
159
- operation_data = {
160
- "type": "SWAP",
161
- "from_token": "0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
162
- "to_token": "0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
163
- "amount_in": "1000000000000000000",
164
- "amount_out": "995000000000000000",
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.get_vault_transactions.return_value = mock_transactions
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(
@@ -24,7 +24,7 @@ The PoolClient will automatically:
24
24
  ### Initialize the Adapter
25
25
 
26
26
  ```python
27
- from wayfinder_paths.vaults.adapters.pool_adapter.adapter import PoolAdapter
27
+ from wayfinder_paths.adapters.pool_adapter.adapter import PoolAdapter
28
28
 
29
29
  # No configuration needed - uses PoolClient with automatic settings
30
30
  adapter = PoolAdapter()
@@ -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/vaults/adapters/pool_adapter/test_adapter.py -v
200
+ pytest wayfinder_paths/adapters/pool_adapter/test_adapter.py -v
213
201
  ```
214
202
 
215
203
  ## Dependencies
@@ -1,7 +1,12 @@
1
1
  from typing import Any
2
2
 
3
3
  from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
4
- from wayfinder_paths.core.clients.PoolClient import PoolClient
4
+ from wayfinder_paths.core.clients.PoolClient import (
5
+ LlamaMatch,
6
+ LlamaReport,
7
+ PoolClient,
8
+ PoolList,
9
+ )
5
10
 
6
11
 
7
12
  class PoolAdapter(BaseAdapter):
@@ -27,7 +32,7 @@ class PoolAdapter(BaseAdapter):
27
32
 
28
33
  async def get_pools_by_ids(
29
34
  self, pool_ids: list[str], merge_external: bool | None = None
30
- ) -> tuple[bool, Any]:
35
+ ) -> tuple[bool, PoolList | str]:
31
36
  """
32
37
  Get pool information by pool IDs.
33
38
 
@@ -50,7 +55,7 @@ class PoolAdapter(BaseAdapter):
50
55
 
51
56
  async def get_all_pools(
52
57
  self, merge_external: bool | None = None
53
- ) -> tuple[bool, Any]:
58
+ ) -> tuple[bool, PoolList | str]:
54
59
  """
55
60
  Get all available pools.
56
61
 
@@ -67,21 +72,7 @@ class PoolAdapter(BaseAdapter):
67
72
  self.logger.error(f"Error fetching all pools: {e}")
68
73
  return (False, str(e))
69
74
 
70
- async def get_combined_pool_reports(self) -> tuple[bool, Any]:
71
- """
72
- Get combined pool reports with analytics.
73
-
74
- Returns:
75
- Tuple of (success, data) where data is combined reports or error message
76
- """
77
- try:
78
- data = await self.pool_client.get_combined_pool_reports()
79
- return (True, data)
80
- except Exception as e:
81
- self.logger.error(f"Error fetching combined pool reports: {e}")
82
- return (False, str(e))
83
-
84
- async def get_llama_matches(self) -> tuple[bool, Any]:
75
+ async def get_llama_matches(self) -> tuple[bool, dict[str, LlamaMatch] | str]:
85
76
  """
86
77
  Get Llama protocol matches for pools.
87
78
 
@@ -95,7 +86,9 @@ class PoolAdapter(BaseAdapter):
95
86
  self.logger.error(f"Error fetching Llama matches: {e}")
96
87
  return (False, str(e))
97
88
 
98
- async def get_llama_reports(self, identifiers: list[str]) -> tuple[bool, Any]:
89
+ async def get_llama_reports(
90
+ self, identifiers: list[str]
91
+ ) -> tuple[bool, dict[str, LlamaReport] | str]:
99
92
  """
100
93
  Get Llama reports for specific identifiers.
101
94
 
@@ -1,5 +1,5 @@
1
1
  schema_version: "0.1"
2
- entrypoint: "vaults.adapters.pool_adapter.adapter.PoolAdapter"
2
+ entrypoint: "adapters.pool_adapter.adapter.PoolAdapter"
3
3
  capabilities:
4
4
  - "pool.read"
5
5
  - "pool.analytics"
@@ -2,7 +2,7 @@ from unittest.mock import AsyncMock, patch
2
2
 
3
3
  import pytest
4
4
 
5
- from wayfinder_paths.vaults.adapters.pool_adapter.adapter import PoolAdapter
5
+ from wayfinder_paths.adapters.pool_adapter.adapter import PoolAdapter
6
6
 
7
7
 
8
8
  class TestPoolAdapter:
@@ -18,7 +18,7 @@ class TestPoolAdapter:
18
18
  def adapter(self, mock_pool_client):
19
19
  """Create a PoolAdapter instance with mocked client for testing"""
20
20
  with patch(
21
- "vaults.adapters.pool_adapter.adapter.PoolClient",
21
+ "adapters.pool_adapter.adapter.PoolClient",
22
22
  return_value=mock_pool_client,
23
23
  ):
24
24
  return PoolAdapter()
@@ -20,7 +20,7 @@ The TokenClient will automatically:
20
20
  ### Initialize the Adapter
21
21
 
22
22
  ```python
23
- from wayfinder_paths.vaults.adapters.token_adapter.adapter import TokenAdapter
23
+ from wayfinder_paths.adapters.token_adapter.adapter import TokenAdapter
24
24
 
25
25
  # No configuration needed - uses TokenClient with automatic settings
26
26
  adapter = TokenAdapter()
@@ -1,7 +1,11 @@
1
1
  from typing import Any
2
2
 
3
3
  from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
4
- from wayfinder_paths.core.clients.TokenClient import TokenClient
4
+ from wayfinder_paths.core.clients.TokenClient import (
5
+ GasToken,
6
+ TokenClient,
7
+ TokenDetails,
8
+ )
5
9
 
6
10
 
7
11
  class TokenAdapter(BaseAdapter):
@@ -20,7 +24,7 @@ class TokenAdapter(BaseAdapter):
20
24
  super().__init__("token_adapter", config)
21
25
  self.token_client = token_client or TokenClient()
22
26
 
23
- async def get_token(self, query: str) -> tuple[bool, Any]:
27
+ async def get_token(self, query: str) -> tuple[bool, TokenDetails | str]:
24
28
  """
25
29
  Get token data by address using the token-details endpoint.
26
30
 
@@ -39,7 +43,7 @@ class TokenAdapter(BaseAdapter):
39
43
  self.logger.error(f"Error getting token by query {query}: {e}")
40
44
  return (False, str(e))
41
45
 
42
- async def get_token_price(self, token_id: str) -> tuple[bool, Any]:
46
+ async def get_token_price(self, token_id: str) -> tuple[bool, dict[str, Any] | str]:
43
47
  """
44
48
  Get token price by token ID or address using the token-details endpoint.
45
49
 
@@ -72,7 +76,7 @@ class TokenAdapter(BaseAdapter):
72
76
  self.logger.error(f"Error getting token price for {token_id}: {e}")
73
77
  return (False, str(e))
74
78
 
75
- async def get_gas_token(self, chain_code: str) -> tuple[bool, Any]:
79
+ async def get_gas_token(self, chain_code: str) -> tuple[bool, GasToken | str]:
76
80
  """
77
81
  Get gas token for a given chain code.
78
82
 
@@ -0,0 +1,26 @@
1
+ {
2
+ "basic_usage": {
3
+ "description": "Basic usage of TokenAdapter to get token information",
4
+ "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# Get token by address\nsuccess, data = await adapter.get_token_by_address(\"0x1234567890abcdef1234567890abcdef12345678\")\nif success:\n print(f\"Token symbol: {data.get('symbol')}\")\n print(f\"Token name: {data.get('name')}\")\n print(f\"Decimals: {data.get('decimals')}\")\nelse:\n print(f\"Error: {data}\")"
5
+ },
6
+ "get_by_token_id": {
7
+ "description": "Get token information using token ID",
8
+ "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# Get token by ID\nsuccess, data = await adapter.get_token_by_id(\"token-12345\")\nif success:\n print(f\"Token data: {data}\")\nelse:\n print(f\"Error: {data}\")"
9
+ },
10
+ "flexible_lookup": {
11
+ "description": "Use flexible get_token method that tries both address and token_id",
12
+ "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# Try both address and token_id\nsuccess, data = await adapter.get_token(\n address=\"0x1234567890abcdef1234567890abcdef12345678\",\n token_id=\"token-12345\"\n)\nif success:\n print(f\"Found token: {data}\")\nelse:\n print(f\"Token not found: {data}\")"
13
+ },
14
+ "error_handling": {
15
+ "description": "Proper error handling for various scenarios",
16
+ "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# Handle missing parameters\ntry:\n success, data = await adapter.get_token()\n if not success:\n print(f\"Error: {data}\")\nexcept Exception as e:\n print(f\"Unexpected error: {e}\")\n\n# Handle API errors\nsuccess, data = await adapter.get_token_by_address(\"invalid-address\")\nif not success:\n print(f\"API error: {data}\")\nelse:\n print(f\"Token found: {data}\")"
17
+ },
18
+ "health_check": {
19
+ "description": "Check adapter health and connectivity",
20
+ "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# Check health\nhealth = await adapter.health_check()\nprint(f\"Adapter status: {health['status']}\")\nprint(f\"Connected: {health['connected']}\")\nprint(f\"Adapter type: {health['adapter']}\")\n\nif health['status'] == 'healthy':\n print(\"Adapter is ready to use\")\nelse:\n print(f\"Adapter has issues: {health.get('error', 'Unknown error')}\")"
21
+ },
22
+ "batch_operations": {
23
+ "description": "Perform multiple token lookups efficiently",
24
+ "code": "from adapters.token_adapter.adapter import TokenAdapter\nimport asyncio\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# List of token addresses to lookup\ntoken_addresses = [\n \"0x1234567890abcdef1234567890abcdef12345678\",\n \"0xabcdef1234567890abcdef1234567890abcdef12\",\n \"0x9876543210fedcba9876543210fedcba98765432\"\n]\n\n# Batch lookup\ntoken_data = {}\nfor address in token_addresses:\n success, data = await adapter.get_token_by_address(address)\n if success:\n token_data[address] = data\n else:\n print(f\"Failed to get token for {address}: {data}\")\n\nprint(f\"Successfully retrieved {len(token_data)} tokens\")\nfor address, data in token_data.items():\n print(f\"{address}: {data.get('symbol', 'Unknown')} - {data.get('name', 'Unknown')}\")"
25
+ }
26
+ }
@@ -1,5 +1,5 @@
1
1
  schema_version: "0.1"
2
- entrypoint: "vaults.adapters.token_adapter.adapter.TokenAdapter"
2
+ entrypoint: "adapters.token_adapter.adapter.TokenAdapter"
3
3
  capabilities:
4
4
  - "token.read"
5
5
  dependencies:
@@ -2,7 +2,7 @@ from unittest.mock import patch
2
2
 
3
3
  import pytest
4
4
 
5
- from wayfinder_paths.vaults.adapters.token_adapter.adapter import TokenAdapter
5
+ from wayfinder_paths.adapters.token_adapter.adapter import TokenAdapter
6
6
 
7
7
 
8
8
  class TestTokenAdapter:
@@ -2,10 +2,12 @@
2
2
  "user": {
3
3
  "username": "your_username",
4
4
  "password": "your_password",
5
- "refresh_token": null
5
+ "refresh_token": null,
6
+ "api_key": "sk_live_abc123..."
6
7
  },
7
8
  "system": {
8
9
  "api_base_url": "https://wayfinder.ai/api/v1",
10
+ "api_key": "sk_live_abc123...",
9
11
  "wallets_path": "wallets.json"
10
12
  },
11
13
  "strategy": {
@@ -1,7 +1,7 @@
1
- """Wayfinder Vaults Core Engine"""
1
+ """Wayfinder Paths Core Engine"""
2
2
 
3
3
  from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
4
- from wayfinder_paths.core.engine.VaultJob import VaultJob
4
+ from wayfinder_paths.core.engine.StrategyJob import StrategyJob
5
5
  from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
6
6
 
7
7
  __all__ = [
@@ -9,5 +9,5 @@ __all__ = [
9
9
  "StatusDict",
10
10
  "StatusTuple",
11
11
  "BaseAdapter",
12
- "VaultJob",
12
+ "StrategyJob",
13
13
  ]
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from abc import ABC
2
4
  from typing import Any
3
5
 
@@ -7,7 +9,7 @@ from loguru import logger
7
9
  class BaseAdapter(ABC):
8
10
  """Base adapter class for exchange/protocol integrations"""
9
11
 
10
- adapter_type: str = None
12
+ adapter_type: str | None = None
11
13
 
12
14
  def __init__(self, name: str, config: dict[str, Any] | None = None):
13
15
  self.name = name
@@ -19,7 +21,22 @@ class BaseAdapter(ABC):
19
21
  return True
20
22
 
21
23
  async def get_balance(self, asset: str) -> dict[str, Any]:
22
- """Optional: provide balance. Default is not implemented."""
24
+ """
25
+ Get balance for an asset.
26
+ Optional method that can be overridden by subclasses.
27
+
28
+ Args:
29
+ asset: Asset identifier (token address, token ID, etc.).
30
+
31
+ Returns:
32
+ Dictionary containing balance information.
33
+
34
+ Raises:
35
+ ValueError: If asset is empty or invalid.
36
+ NotImplementedError: If this adapter does not support balance queries.
37
+ """
38
+ if not asset or not isinstance(asset, str) or not asset.strip():
39
+ raise ValueError("asset must be a non-empty string")
23
40
  raise NotImplementedError(
24
41
  f"get_balance not supported by {self.__class__.__name__}"
25
42
  )
@@ -43,6 +60,6 @@ class BaseAdapter(ABC):
43
60
  "adapter": self.adapter_type or self.__class__.__name__,
44
61
  }
45
62
 
46
- async def close(self):
63
+ async def close(self) -> None:
47
64
  """Clean up resources"""
48
65
  pass
@@ -0,0 +1,41 @@
1
+ """Pydantic models for ledger operations."""
2
+
3
+ from typing import Annotated, Any, Literal
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+
8
+ class SWAP(BaseModel):
9
+ """Swap operation."""
10
+
11
+ type: Literal["SWAP"] = "SWAP"
12
+ from_token_id: str
13
+ to_token_id: str
14
+ from_amount: str
15
+ to_amount: str
16
+ from_amount_usd: float
17
+ to_amount_usd: float
18
+ transaction_hash: str | None = None
19
+ transaction_status: str | None = None
20
+ transaction_receipt: dict[str, Any] | None = None
21
+
22
+
23
+ class LEND(BaseModel):
24
+ type: Literal["LEND"] = "LEND"
25
+ contract: str
26
+ amount: int
27
+
28
+
29
+ class UNLEND(BaseModel):
30
+ type: Literal["UNLEND"] = "UNLEND"
31
+ contract: str
32
+ amount: int
33
+
34
+
35
+ # Type alias for operation types (currently only SWAP is used)
36
+ # Add more operation types here as needed
37
+ Operation = SWAP | LEND | UNLEND
38
+
39
+
40
+ class STRAT_OP(BaseModel):
41
+ op_data: Annotated[Operation, Field(discriminator="type")]
@@ -3,8 +3,10 @@ BRAP (Bridge/Router/Adapter Protocol) Client
3
3
  Provides access to quote operations via the public quote endpoint.
4
4
  """
5
5
 
6
+ from __future__ import annotations
7
+
6
8
  import time
7
- from typing import Any
9
+ from typing import Any, NotRequired, Required, TypedDict
8
10
 
9
11
  from loguru import logger
10
12
 
@@ -13,6 +15,23 @@ from wayfinder_paths.core.clients.WayfinderClient import WayfinderClient
13
15
  from wayfinder_paths.core.settings import settings
14
16
 
15
17
 
18
+ class BRAPQuote(TypedDict):
19
+ """BRAP quote response structure"""
20
+
21
+ from_token_address: Required[str]
22
+ to_token_address: Required[str]
23
+ from_chain_id: Required[int]
24
+ to_chain_id: Required[int]
25
+ from_address: Required[str]
26
+ to_address: Required[str]
27
+ amount1: Required[str]
28
+ amount2: NotRequired[str]
29
+ routes: NotRequired[list[dict[str, Any]]]
30
+ fees: NotRequired[dict[str, Any] | None]
31
+ slippage: NotRequired[float | None]
32
+ wayfinder_fee: NotRequired[float | None]
33
+
34
+
16
35
  class BRAPClient(WayfinderClient):
17
36
  """Client for BRAP quote operations"""
18
37
 
@@ -33,7 +52,7 @@ class BRAPClient(WayfinderClient):
33
52
  amount1: str,
34
53
  slippage: float | None = None,
35
54
  wayfinder_fee: float | None = None,
36
- ) -> dict[str, Any]:
55
+ ) -> BRAPQuote:
37
56
  """
38
57
  Get a quote for a bridge/swap operation.
39
58