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.

Files changed (156) hide show
  1. wayfinder_paths/__init__.py +0 -4
  2. wayfinder_paths/adapters/balance_adapter/README.md +0 -1
  3. wayfinder_paths/adapters/balance_adapter/adapter.py +313 -167
  4. wayfinder_paths/adapters/balance_adapter/manifest.yaml +8 -0
  5. wayfinder_paths/adapters/balance_adapter/test_adapter.py +41 -124
  6. wayfinder_paths/adapters/boros_adapter/__init__.py +17 -0
  7. wayfinder_paths/adapters/boros_adapter/adapter.py +1574 -0
  8. wayfinder_paths/adapters/boros_adapter/client.py +476 -0
  9. wayfinder_paths/adapters/boros_adapter/manifest.yaml +10 -0
  10. wayfinder_paths/adapters/boros_adapter/parsers.py +88 -0
  11. wayfinder_paths/adapters/boros_adapter/test_adapter.py +460 -0
  12. wayfinder_paths/adapters/boros_adapter/test_golden.py +156 -0
  13. wayfinder_paths/adapters/boros_adapter/types.py +70 -0
  14. wayfinder_paths/adapters/boros_adapter/utils.py +85 -0
  15. wayfinder_paths/adapters/brap_adapter/README.md +22 -75
  16. wayfinder_paths/adapters/brap_adapter/adapter.py +187 -576
  17. wayfinder_paths/adapters/brap_adapter/examples.json +21 -140
  18. wayfinder_paths/adapters/brap_adapter/manifest.yaml +9 -0
  19. wayfinder_paths/adapters/brap_adapter/test_adapter.py +6 -234
  20. wayfinder_paths/adapters/hyperlend_adapter/adapter.py +180 -92
  21. wayfinder_paths/adapters/hyperlend_adapter/manifest.yaml +9 -0
  22. wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +82 -14
  23. wayfinder_paths/adapters/hyperliquid_adapter/__init__.py +2 -9
  24. wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +586 -61
  25. wayfinder_paths/adapters/hyperliquid_adapter/executor.py +47 -68
  26. wayfinder_paths/adapters/hyperliquid_adapter/manifest.yaml +14 -0
  27. wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +2 -3
  28. wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +17 -21
  29. wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +3 -6
  30. wayfinder_paths/adapters/hyperliquid_adapter/test_executor.py +4 -8
  31. wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +2 -2
  32. wayfinder_paths/adapters/ledger_adapter/README.md +4 -1
  33. wayfinder_paths/adapters/ledger_adapter/adapter.py +3 -3
  34. wayfinder_paths/adapters/ledger_adapter/manifest.yaml +7 -0
  35. wayfinder_paths/adapters/ledger_adapter/test_adapter.py +1 -2
  36. wayfinder_paths/adapters/moonwell_adapter/adapter.py +649 -547
  37. wayfinder_paths/adapters/moonwell_adapter/manifest.yaml +14 -0
  38. wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +160 -239
  39. wayfinder_paths/adapters/multicall_adapter/__init__.py +7 -0
  40. wayfinder_paths/adapters/multicall_adapter/adapter.py +166 -0
  41. wayfinder_paths/adapters/multicall_adapter/manifest.yaml +5 -0
  42. wayfinder_paths/adapters/multicall_adapter/test_adapter.py +97 -0
  43. wayfinder_paths/adapters/pendle_adapter/README.md +102 -0
  44. wayfinder_paths/adapters/pendle_adapter/__init__.py +7 -0
  45. wayfinder_paths/adapters/pendle_adapter/adapter.py +1992 -0
  46. wayfinder_paths/adapters/pendle_adapter/examples.json +11 -0
  47. wayfinder_paths/adapters/pendle_adapter/manifest.yaml +21 -0
  48. wayfinder_paths/adapters/pendle_adapter/test_adapter.py +666 -0
  49. wayfinder_paths/adapters/pool_adapter/manifest.yaml +6 -0
  50. wayfinder_paths/adapters/token_adapter/adapter.py +14 -0
  51. wayfinder_paths/adapters/token_adapter/examples.json +0 -4
  52. wayfinder_paths/adapters/token_adapter/manifest.yaml +7 -0
  53. wayfinder_paths/conftest.py +24 -17
  54. wayfinder_paths/core/__init__.py +0 -3
  55. wayfinder_paths/core/adapters/BaseAdapter.py +0 -25
  56. wayfinder_paths/core/adapters/models.py +17 -7
  57. wayfinder_paths/core/clients/BRAPClient.py +4 -1
  58. wayfinder_paths/core/clients/ClientManager.py +0 -7
  59. wayfinder_paths/core/clients/LedgerClient.py +196 -172
  60. wayfinder_paths/core/clients/TokenClient.py +47 -1
  61. wayfinder_paths/core/clients/WayfinderClient.py +1 -3
  62. wayfinder_paths/core/clients/__init__.py +0 -5
  63. wayfinder_paths/core/clients/protocols.py +21 -35
  64. wayfinder_paths/core/clients/test_ledger_client.py +448 -0
  65. wayfinder_paths/core/config.py +10 -162
  66. wayfinder_paths/core/constants/__init__.py +73 -2
  67. wayfinder_paths/core/constants/base.py +8 -17
  68. wayfinder_paths/core/constants/chains.py +36 -0
  69. wayfinder_paths/core/constants/contracts.py +52 -0
  70. wayfinder_paths/core/constants/erc20_abi.py +0 -1
  71. wayfinder_paths/core/constants/hyperlend_abi.py +0 -4
  72. wayfinder_paths/core/constants/hyperliquid.py +16 -0
  73. wayfinder_paths/core/constants/moonwell_abi.py +0 -15
  74. wayfinder_paths/core/constants/tokens.py +9 -0
  75. wayfinder_paths/core/engine/manifest.py +66 -0
  76. wayfinder_paths/core/strategies/Strategy.py +0 -71
  77. wayfinder_paths/core/strategies/__init__.py +10 -1
  78. wayfinder_paths/core/strategies/opa_loop.py +167 -0
  79. wayfinder_paths/core/utils/evm_helpers.py +5 -15
  80. wayfinder_paths/core/utils/test_transaction.py +289 -0
  81. wayfinder_paths/core/utils/tokens.py +28 -0
  82. wayfinder_paths/core/utils/transaction.py +57 -8
  83. wayfinder_paths/core/utils/web3.py +8 -3
  84. wayfinder_paths/mcp/__init__.py +5 -0
  85. wayfinder_paths/mcp/preview.py +185 -0
  86. wayfinder_paths/mcp/scripting.py +84 -0
  87. wayfinder_paths/mcp/server.py +52 -0
  88. wayfinder_paths/mcp/state/profile_store.py +195 -0
  89. wayfinder_paths/mcp/state/store.py +89 -0
  90. wayfinder_paths/mcp/test_scripting.py +267 -0
  91. wayfinder_paths/mcp/tools/__init__.py +0 -0
  92. wayfinder_paths/mcp/tools/balances.py +290 -0
  93. wayfinder_paths/mcp/tools/discovery.py +158 -0
  94. wayfinder_paths/mcp/tools/execute.py +770 -0
  95. wayfinder_paths/mcp/tools/hyperliquid.py +931 -0
  96. wayfinder_paths/mcp/tools/quotes.py +288 -0
  97. wayfinder_paths/mcp/tools/run_script.py +286 -0
  98. wayfinder_paths/mcp/tools/strategies.py +188 -0
  99. wayfinder_paths/mcp/tools/tokens.py +46 -0
  100. wayfinder_paths/mcp/tools/wallets.py +354 -0
  101. wayfinder_paths/mcp/utils.py +129 -0
  102. wayfinder_paths/policies/enso.py +1 -2
  103. wayfinder_paths/policies/hyper_evm.py +6 -3
  104. wayfinder_paths/policies/hyperlend.py +1 -2
  105. wayfinder_paths/policies/hyperliquid.py +1 -1
  106. wayfinder_paths/policies/lifi.py +18 -0
  107. wayfinder_paths/policies/moonwell.py +12 -7
  108. wayfinder_paths/policies/prjx.py +1 -3
  109. wayfinder_paths/policies/util.py +8 -2
  110. wayfinder_paths/run_strategy.py +97 -300
  111. wayfinder_paths/strategies/basis_trading_strategy/constants.py +3 -1
  112. wayfinder_paths/strategies/basis_trading_strategy/strategy.py +47 -133
  113. wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +24 -53
  114. wayfinder_paths/strategies/boros_hype_strategy/__init__.py +3 -0
  115. wayfinder_paths/strategies/boros_hype_strategy/boros_ops_mixin.py +450 -0
  116. wayfinder_paths/strategies/boros_hype_strategy/constants.py +255 -0
  117. wayfinder_paths/strategies/boros_hype_strategy/examples.json +37 -0
  118. wayfinder_paths/strategies/boros_hype_strategy/hyperevm_ops_mixin.py +114 -0
  119. wayfinder_paths/strategies/boros_hype_strategy/hyperliquid_ops_mixin.py +642 -0
  120. wayfinder_paths/strategies/boros_hype_strategy/manifest.yaml +36 -0
  121. wayfinder_paths/strategies/boros_hype_strategy/planner.py +460 -0
  122. wayfinder_paths/strategies/boros_hype_strategy/risk_ops_mixin.py +886 -0
  123. wayfinder_paths/strategies/boros_hype_strategy/snapshot_mixin.py +494 -0
  124. wayfinder_paths/strategies/boros_hype_strategy/strategy.py +1194 -0
  125. wayfinder_paths/strategies/boros_hype_strategy/test_planner_golden.py +374 -0
  126. wayfinder_paths/{templates/strategy → strategies/boros_hype_strategy}/test_strategy.py +99 -63
  127. wayfinder_paths/strategies/boros_hype_strategy/types.py +365 -0
  128. wayfinder_paths/strategies/boros_hype_strategy/withdraw_mixin.py +997 -0
  129. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +15 -23
  130. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +27 -62
  131. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +84 -58
  132. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +5 -15
  133. wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +69 -164
  134. wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +43 -76
  135. wayfinder_paths/tests/test_mcp_quote_swap.py +165 -0
  136. wayfinder_paths/tests/test_test_coverage.py +1 -4
  137. wayfinder_paths-0.1.24.dist-info/METADATA +378 -0
  138. wayfinder_paths-0.1.24.dist-info/RECORD +185 -0
  139. {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.24.dist-info}/WHEEL +1 -1
  140. wayfinder_paths/core/clients/WalletClient.py +0 -41
  141. wayfinder_paths/core/engine/StrategyJob.py +0 -110
  142. wayfinder_paths/core/services/test_local_evm_txn.py +0 -145
  143. wayfinder_paths/scripts/create_strategy.py +0 -139
  144. wayfinder_paths/scripts/make_wallets.py +0 -142
  145. wayfinder_paths/templates/adapter/README.md +0 -150
  146. wayfinder_paths/templates/adapter/adapter.py +0 -16
  147. wayfinder_paths/templates/adapter/examples.json +0 -8
  148. wayfinder_paths/templates/adapter/test_adapter.py +0 -30
  149. wayfinder_paths/templates/strategy/README.md +0 -186
  150. wayfinder_paths/templates/strategy/examples.json +0 -11
  151. wayfinder_paths/templates/strategy/strategy.py +0 -35
  152. wayfinder_paths/tests/test_smoke_manifest.py +0 -63
  153. wayfinder_paths-0.1.22.dist-info/METADATA +0 -355
  154. wayfinder_paths-0.1.22.dist-info/RECORD +0 -129
  155. /wayfinder_paths/{scripts → mcp/state}/__init__.py +0 -0
  156. {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.24.dist-info}/LICENSE +0 -0
@@ -11,10 +11,6 @@
11
11
  "description": "Proper error handling for various scenarios",
12
12
  "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# Handle API errors\nsuccess, data = await adapter.get_token(\"invalid-address\")\nif not success:\n print(f\"API error: {data}\")\nelse:\n print(f\"Token found: {data}\")"
13
13
  },
14
- "health_check": {
15
- "description": "Check adapter health and connectivity",
16
- "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')}\")"
17
- },
18
14
  "batch_operations": {
19
15
  "description": "Perform multiple token lookups efficiently",
20
16
  "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# List of token addresses to lookup (Base chain)\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(address, chain_id=8453)\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')}\")"
@@ -0,0 +1,7 @@
1
+ schema_version: "0.1"
2
+ entrypoint: "adapters.token_adapter.adapter.TokenAdapter"
3
+ capabilities:
4
+ - "token.read"
5
+ - "token.price"
6
+ - "token.gas"
7
+ dependencies: []
@@ -1,23 +1,30 @@
1
1
  import sys
2
2
  from pathlib import Path
3
3
 
4
- # This needs to be at index 0 to take precedence over repo root 'tests/' directory
5
- _wayfinder_path_dir = Path(__file__).parent
6
- _wayfinder_path_str = str(_wayfinder_path_dir)
4
+ import pytest
5
+
6
+ # Add repo root to path so tests.test_utils can be imported
7
+ _repo_root = Path(__file__).parent.parent
8
+ _repo_root_str = str(_repo_root)
7
9
 
8
10
 
9
11
  def pytest_configure(config):
10
- if _wayfinder_path_str not in sys.path:
11
- sys.path.insert(0, _wayfinder_path_str)
12
- elif sys.path.index(_wayfinder_path_str) > 0:
13
- # Move to front if it exists but isn't first
14
- sys.path.remove(_wayfinder_path_str)
15
- sys.path.insert(0, _wayfinder_path_str)
16
-
17
-
18
- # Also set it immediately (in case pytest_configure hasn't run yet)
19
- if _wayfinder_path_str not in sys.path:
20
- sys.path.insert(0, _wayfinder_path_str)
21
- elif sys.path.index(_wayfinder_path_str) > 0:
22
- sys.path.remove(_wayfinder_path_str)
23
- sys.path.insert(0, _wayfinder_path_str)
12
+ config.addinivalue_line("markers", "smoke: mark test as a smoke test")
13
+ if _repo_root_str not in sys.path:
14
+ sys.path.insert(0, _repo_root_str)
15
+ elif sys.path.index(_repo_root_str) > 0:
16
+ sys.path.remove(_repo_root_str)
17
+ sys.path.insert(0, _repo_root_str)
18
+
19
+
20
+ def pytest_collection_modifyitems(config, items):
21
+ for item in items:
22
+ if "smoke" in item.nodeid:
23
+ item.add_marker(pytest.mark.smoke)
24
+
25
+
26
+ if _repo_root_str not in sys.path:
27
+ sys.path.insert(0, _repo_root_str)
28
+ elif sys.path.index(_repo_root_str) > 0:
29
+ sys.path.remove(_repo_root_str)
30
+ sys.path.insert(0, _repo_root_str)
@@ -1,7 +1,5 @@
1
1
  from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
2
- from wayfinder_paths.core.engine.StrategyJob import StrategyJob
3
2
  from wayfinder_paths.core.strategies.Strategy import (
4
- LiquidationResult,
5
3
  StatusDict,
6
4
  StatusTuple,
7
5
  Strategy,
@@ -12,5 +10,4 @@ __all__ = [
12
10
  "StatusDict",
13
11
  "StatusTuple",
14
12
  "BaseAdapter",
15
- "StrategyJob",
16
13
  ]
@@ -14,30 +14,5 @@ class BaseAdapter(ABC):
14
14
  self.config = config or {}
15
15
  self.logger = logger.bind(adapter=self.__class__.__name__)
16
16
 
17
- async def connect(self) -> bool:
18
- return True
19
-
20
- async def get_balance(self, asset: str) -> dict[str, Any]:
21
- if not asset or not isinstance(asset, str) or not asset.strip():
22
- raise ValueError("asset must be a non-empty string")
23
- raise NotImplementedError(
24
- f"get_balance not supported by {self.__class__.__name__}"
25
- )
26
-
27
- async def health_check(self) -> dict[str, Any]:
28
- try:
29
- connected = await self.connect()
30
- return {
31
- "status": "healthy" if connected else "unhealthy",
32
- "connected": connected,
33
- "adapter": self.adapter_type or self.__class__.__name__,
34
- }
35
- except Exception as e:
36
- return {
37
- "status": "error",
38
- "error": str(e),
39
- "adapter": self.adapter_type or self.__class__.__name__,
40
- }
41
-
42
17
  async def close(self) -> None:
43
18
  pass
@@ -4,9 +4,11 @@ from pydantic import BaseModel, Field
4
4
 
5
5
 
6
6
  class OperationBase(BaseModel):
7
- adapter: str
8
- transaction_hash: str | None
9
- transaction_chain_id: int | None
7
+ # These are provided by adapters at execution time, but tests and callers may
8
+ # construct operations without them (e.g., for bookkeeping payloads).
9
+ adapter: str = "unknown"
10
+ transaction_hash: str | None = None
11
+ transaction_chain_id: int | None = None
10
12
 
11
13
 
12
14
  class SWAP(OperationBase):
@@ -23,14 +25,22 @@ class SWAP(OperationBase):
23
25
 
24
26
  class LEND(OperationBase):
25
27
  type: Literal["LEND"] = "LEND"
26
- contract: str
27
- amount: int
28
+ token_address: str
29
+ pool_address: str
30
+ amount: str
31
+ amount_usd: float
32
+ transaction_status: str | None = None
33
+ transaction_receipt: dict[str, Any] | None = None
28
34
 
29
35
 
30
36
  class UNLEND(OperationBase):
31
37
  type: Literal["UNLEND"] = "UNLEND"
32
- contract: str
33
- amount: int
38
+ token_address: str
39
+ pool_address: str
40
+ amount: str
41
+ amount_usd: float
42
+ transaction_status: str | None = None
43
+ transaction_receipt: dict[str, Any] | None = None
34
44
 
35
45
 
36
46
  # Type alias for operation types (currently only SWAP is used)
@@ -72,7 +72,7 @@ class BRAPQuoteResponse(TypedDict):
72
72
  class BRAPClient(WayfinderClient):
73
73
  def __init__(self):
74
74
  super().__init__()
75
- self.api_base_url = f"{get_api_base_url()}/v1/blockchain/braps"
75
+ self.api_base_url = f"{get_api_base_url()}/blockchain/braps"
76
76
 
77
77
  async def get_quote(
78
78
  self,
@@ -83,6 +83,7 @@ class BRAPClient(WayfinderClient):
83
83
  to_chain: int,
84
84
  from_wallet: str,
85
85
  from_amount: str,
86
+ slippage: float | None = None,
86
87
  ) -> BRAPQuoteResponse: # type: ignore # noqa: E501
87
88
  logger.info(
88
89
  f"Getting BRAP quote: {from_token} -> {to_token} (chain {from_chain} -> {to_chain})"
@@ -100,6 +101,8 @@ class BRAPClient(WayfinderClient):
100
101
  "from_wallet": from_wallet,
101
102
  "from_amount": from_amount,
102
103
  }
104
+ if slippage is not None:
105
+ params["slippage"] = slippage
103
106
 
104
107
  try:
105
108
  response = await self._authed_request("GET", url, params=params, headers={})
@@ -10,10 +10,8 @@ from wayfinder_paths.core.clients.protocols import (
10
10
  LedgerClientProtocol,
11
11
  PoolClientProtocol,
12
12
  TokenClientProtocol,
13
- WalletClientProtocol,
14
13
  )
15
14
  from wayfinder_paths.core.clients.TokenClient import TokenClient
16
- from wayfinder_paths.core.clients.WalletClient import WalletClient
17
15
 
18
16
 
19
17
  class ClientManager:
@@ -26,7 +24,6 @@ class ClientManager:
26
24
  self._skip_auth = skip_auth
27
25
 
28
26
  self._token_client: TokenClientProtocol | None = None
29
- self._wallet_client: WalletClientProtocol | None = None
30
27
  self._ledger_client: LedgerClientProtocol | None = None
31
28
  self._pool_client: PoolClientProtocol | None = None
32
29
  self._hyperlend_client: HyperlendClientProtocol | None = None
@@ -62,10 +59,6 @@ class ClientManager:
62
59
  "_hyperlend_client", "hyperlend", HyperlendClient
63
60
  )
64
61
 
65
- @property
66
- def wallet(self) -> WalletClientProtocol:
67
- return self._get_or_create_client("_wallet_client", "wallet", WalletClient)
68
-
69
62
  @property
70
63
  def brap(self) -> BRAPClientProtocol:
71
64
  return self._get_or_create_client("_brap_client", "brap", BRAPClient)