wayfinder-paths 0.1.1__py3-none-any.whl → 0.1.3__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.

@@ -0,0 +1,54 @@
1
+ from wayfinder_paths.vaults.policies.util import allow_functions
2
+
3
+ WETH = "0x4200000000000000000000000000000000000006"
4
+
5
+ M_USDC = "0xEdc817A28E8B93B03976FBd4a3dDBc9f7D176c22"
6
+ M_WETH = "0x628ff693426583D9a7FB391E54366292F509D457"
7
+ M_WSTETH = "0x627Fe393Bc6EdDA28e99AE648fD6fF362514304b"
8
+
9
+ COMPTROLLER = "0xfbb21d0380bee3312b33c4353c8936a0f13ef26c"
10
+
11
+
12
+ async def weth_deposit():
13
+ return await allow_functions(
14
+ policy_name="Allow WETH Deposit",
15
+ abi_chain_id=8453,
16
+ address=WETH,
17
+ function_names=["deposit"],
18
+ )
19
+
20
+
21
+ async def musdc_mint_or_approve_or_redeem():
22
+ return await allow_functions(
23
+ policy_name="Allow MUSDC Mint or Approve or Redeem",
24
+ abi_chain_id=8453,
25
+ address=M_USDC,
26
+ function_names=["mint", "approve", "redeem"],
27
+ )
28
+
29
+
30
+ async def mweth_approve_or_borrow_or_repay():
31
+ return await allow_functions(
32
+ policy_name="Allow MWETH Approve or Borrow or Repay",
33
+ abi_chain_id=8453,
34
+ address=M_WETH,
35
+ function_names=["approve", "borrow", "repayBorrow"],
36
+ )
37
+
38
+
39
+ async def mwsteth_approve_or_mint_or_redeem():
40
+ return await allow_functions(
41
+ policy_name="Allow MWSTETH Approve or Mint or Redeem",
42
+ abi_chain_id=8453,
43
+ address=M_WSTETH,
44
+ function_names=["approve", "mint", "redeem"],
45
+ )
46
+
47
+
48
+ async def moonwell_comptroller_enter_markets_or_claim_rewards():
49
+ return await allow_functions(
50
+ policy_name="Allow Moonwell Comptroller Enter Markets or Claim Rewards",
51
+ abi_chain_id=8453,
52
+ address=COMPTROLLER,
53
+ function_names=["enterMarkets", "claimReward"],
54
+ )
@@ -0,0 +1,30 @@
1
+ from wayfinder_paths.vaults.policies.util import allow_functions
2
+
3
+ PRJX_ROUTER = "0x1ebdfc75ffe3ba3de61e7138a3e8706ac841af9b"
4
+ PRJX_NPM = "0xeAd19AE861c29bBb2101E834922B2FEee69B9091"
5
+
6
+
7
+ async def prjx_swap():
8
+ return await allow_functions(
9
+ policy_name="Allow PRJX Swap",
10
+ abi_chain_id=999,
11
+ address=PRJX_ROUTER,
12
+ function_names=[
13
+ "exactInput",
14
+ "exactInputSingle",
15
+ "exactOutput",
16
+ "exactOutputSingle",
17
+ ],
18
+ )
19
+
20
+
21
+ async def prjx_npm():
22
+ return await allow_functions(
23
+ policy_name="Allow PRJX NPM",
24
+ abi_chain_id=999,
25
+ address=PRJX_NPM,
26
+ function_names=[
27
+ "increaseLiquidity",
28
+ "decreaseLiquidity",
29
+ ],
30
+ )
@@ -0,0 +1,27 @@
1
+ from wayfinder_paths.core.utils.evm_helpers import get_abi_filtered
2
+
3
+
4
+ async def allow_functions(
5
+ policy_name: str, abi_chain_id: int, address: str, function_names: list[str]
6
+ ):
7
+ # Note: ChainID is just for fetching ABI, doesn't appear in the final policy. Doesn't bind a strict chain.
8
+ return {
9
+ "name": policy_name,
10
+ "method": "eth_signTransaction",
11
+ "action": "ALLOW",
12
+ "conditions": [
13
+ {
14
+ "field_source": "ethereum_transaction",
15
+ "field": "to",
16
+ "operator": "eq",
17
+ "value": address,
18
+ },
19
+ {
20
+ "field_source": "ethereum_calldata",
21
+ "field": "function_name",
22
+ "abi": await get_abi_filtered(abi_chain_id, address, function_names),
23
+ "operator": "in",
24
+ "value": function_names,
25
+ },
26
+ ],
27
+ }
@@ -17,6 +17,14 @@ from wayfinder_paths.core.services.local_token_txn import (
17
17
  LocalTokenTxnService,
18
18
  )
19
19
  from wayfinder_paths.core.services.web3_service import DefaultWeb3Service
20
+ from wayfinder_paths.core.strategies.descriptors import (
21
+ Complexity,
22
+ Directionality,
23
+ Frequency,
24
+ StratDescriptor,
25
+ TokenExposure,
26
+ Volatility,
27
+ )
20
28
  from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
21
29
  from wayfinder_paths.core.wallets.WalletManager import WalletManager
22
30
  from wayfinder_paths.vaults.adapters.balance_adapter.adapter import BalanceAdapter
@@ -24,6 +32,21 @@ from wayfinder_paths.vaults.adapters.brap_adapter.adapter import BRAPAdapter
24
32
  from wayfinder_paths.vaults.adapters.hyperlend_adapter.adapter import HyperlendAdapter
25
33
  from wayfinder_paths.vaults.adapters.ledger_adapter.adapter import LedgerAdapter
26
34
  from wayfinder_paths.vaults.adapters.token_adapter.adapter import TokenAdapter
35
+ from wayfinder_paths.vaults.policies.enso import ENSO_ROUTER, enso_swap
36
+ from wayfinder_paths.vaults.policies.erc20 import erc20_spender_for_any_token
37
+ from wayfinder_paths.vaults.policies.hyper_evm import (
38
+ hypecore_sentinel_deposit,
39
+ whype_deposit_and_withdraw,
40
+ )
41
+ from wayfinder_paths.vaults.policies.hyperlend import (
42
+ HYPERLEND_POOL,
43
+ hyperlend_supply_and_withdraw,
44
+ )
45
+ from wayfinder_paths.vaults.policies.hyperliquid import (
46
+ any_hyperliquid_l1_payload,
47
+ any_hyperliquid_user_payload,
48
+ )
49
+ from wayfinder_paths.vaults.policies.prjx import PRJX_ROUTER, prjx_swap
27
50
 
28
51
  SYMBOL_TRANSLATION_TABLE = str.maketrans(
29
52
  {
@@ -36,7 +59,7 @@ WRAPPED_HYPE_ADDRESS = "0x5555555555555555555555555555555555555555"
36
59
 
37
60
 
38
61
  class HyperlendStableYieldStrategy(Strategy):
39
- name = "Hyperland Stable Yield Strategy"
62
+ name = "HyperLend Stable Optimizer"
40
63
 
41
64
  # Strategy parameters
42
65
  APY_SHORT_CIRCUIT_THRESHOLD = None
@@ -61,82 +84,110 @@ class HyperlendStableYieldStrategy(Strategy):
61
84
  P_BEST_ROTATION_THRESHOLD = 0.4
62
85
  MAX_CANDIDATES = 5
63
86
  MIN_STABLE_SWAP_TOKENS = 1e-3
64
-
65
- description = f"""Multi-strategy allocator that converts USDT0 into the most consistently rewarding HyperLend stablecoin and continuously checks if a rotation is justified.
66
- **What it does:** Pulls USDT0 from the main wallet, ensures a small HYPE safety buffer for gas, swaps the remaining stable balance into candidate markets, and supplies
67
- liquidity to HyperLend. Hourly rate histories are aggregated into a 7-day panel and routed through a block-bootstrap tournament (horizon {HORIZON_HOURS}h, block length {BLOCK_LEN}, {TRIALS:,}
68
- trials, {HALFLIFE_DAYS}-day half-life weighting) to estimate which asset has the highest probability of outperforming peers. USDT0 is the LayerZero bridgable stablecoin for USDT.
69
- **Exposure type:** Market-neutral stablecoin lending on HyperEVM with automated rotation into whichever pool offers the strongest risk-adjusted lending yield.
70
- **Chains:** HyperEVM only (HyperLend pool suite).
71
- **Deposit/Withdrawal:** Deposits move USDT0 from the main wallet into the strategy wallet, top up a minimal HYPE gas buffer, rotate into the selected stable, and lend it via HyperLend.
72
- Withdrawals unwind the lend position, convert balances back to USDT, and return funds (plus residual HYPE) to the main wallet.
73
- **Gas**: Requires HYPE on HypeEVM. Arbitrary amount of funding gas is accepted via vault wallet transfers.
74
- """
75
- summary = (
76
- "Recency-weighted HyperLend stablecoin optimizer that bootstraps 7-day rate history "
77
- f"(horizon {HORIZON_HOURS}h, {BLOCK_LEN}-hour blocks, {TRIALS:,} simulations) to pick the top "
78
- "performer, funds with USDT0, tops up a small HYPE gas buffer, and defaults to a hysteresis "
79
- f"rotation band (dwell={HYSTERESIS_DWELL_HOURS}h, z={HYSTERESIS_Z:.2f}) to avoid churn while still "
80
- "short-circuiting when yield gaps are extreme."
81
- )
82
-
83
- config = {
84
- "deposit": {
85
- "description": "Move USDT0 into the vault, ensure a small HYPE gas buffer, and supply the best HyperLend stable.",
86
- "parameters": {
87
- "main_token_amount": {
88
- "type": "float",
89
- "unit": "USDT0 tokens",
90
- "description": "Amount of USDT0 to allocate to HyperLend.",
91
- "minimum": 1.0, # TODO: 10
92
- "examples": ["100.0", "250.5"],
93
- },
94
- "gas_token_amount": {
95
- "type": "float",
96
- "unit": "HYPE tokens",
97
- "description": "Amount of HYPE to top up into the vault wallet to cover gas costs.",
98
- "minimum": 0.0,
99
- "maximum": GAS_MAXIMUM,
100
- "recommended": GAS_MAXIMUM,
87
+ MAX_GAS = 0.1 # hype float
88
+
89
+ INFO = StratDescriptor(
90
+ description=f"""Multi-strategy allocator that converts USDT0 into the most consistently rewarding HyperLend stablecoin and continuously checks if a rotation is justified.
91
+ **What it does:** Pulls USDT0 from the main wallet, ensures a small HYPE safety buffer for gas, swaps the remaining stable balance into candidate markets, and supplies
92
+ liquidity to HyperLend. Hourly rate histories are aggregated into a 7-day panel and routed through a block-bootstrap tournament (horizon {HORIZON_HOURS}h, block length {BLOCK_LEN}, {TRIALS:,}
93
+ trials, {HALFLIFE_DAYS}-day half-life weighting) to estimate which asset has the highest probability of outperforming peers. USDT0 is the LayerZero bridgable stablecoin for USDT.
94
+ **Exposure type:** Market-neutral stablecoin lending on HyperEVM with automated rotation into whichever pool offers the strongest risk-adjusted lending yield.
95
+ **Chains:** HyperEVM only (HyperLend pool suite).
96
+ **Deposit/Withdrawal:** Deposits move USDT0 from the main wallet into the strategy wallet, top up a minimal HYPE gas buffer, rotate into the selected stable, and lend it via HyperLend.
97
+ Withdrawals unwind the lend position, convert balances back to USDT, and return funds (plus residual HYPE) to the main wallet.
98
+ **Gas**: Requires HYPE on HypeEVM. Arbitrary amount of funding gas is accepted via vault wallet transfers.
99
+ """,
100
+ summary=(
101
+ "Recency-weighted HyperLend stablecoin optimizer that bootstraps 7-day rate history "
102
+ f"(horizon {HORIZON_HOURS}h, {BLOCK_LEN}-hour blocks, {TRIALS:,} simulations) to pick the top "
103
+ "performer, funds with USDT0, tops up a small HYPE gas buffer, and defaults to a hysteresis "
104
+ f"rotation band (dwell={HYSTERESIS_DWELL_HOURS}h, z={HYSTERESIS_Z:.2f}) to avoid churn while still "
105
+ "short-circuiting when yield gaps are extreme."
106
+ ),
107
+ gas_token_symbol="HYPE",
108
+ gas_token_id="hyperliquid-hyperevm",
109
+ deposit_token_id="usdt0-hyperevm",
110
+ minimum_net_deposit=10,
111
+ gas_maximum=MAX_GAS, # hype float
112
+ gas_threshold=MAX_GAS / 3,
113
+ # risk indicators
114
+ volatility=Volatility.LOW,
115
+ volatility_description_short=(
116
+ "Pure HyperLend stablecoin lending keeps NAV steady aside from rate drift."
117
+ ),
118
+ directionality=Directionality.MARKET_NEUTRAL,
119
+ directionality_description=(
120
+ "Rotates capital between USD stables so exposure stays market neutral."
121
+ ),
122
+ complexity=Complexity.LOW,
123
+ complexity_description="Agent handles optimal pool finding, swaps, and lend transactions automatically.",
124
+ token_exposure=TokenExposure.STABLECOINS,
125
+ token_exposure_description=(
126
+ "Only HyperEVM USD stables (USDT0 and peers), no volatile tokens."
127
+ ),
128
+ frequency=Frequency.LOW,
129
+ frequency_description=(
130
+ "Updates every 2 hours; rotations infrequent (weekly cooldowns)."
131
+ ),
132
+ return_drivers=["lend APY", "pool yield"],
133
+ config={
134
+ "deposit": {
135
+ "description": "Move USDT0 into the vault, ensure a small HYPE gas buffer, and supply the best HyperLend stable.",
136
+ "parameters": {
137
+ "main_token_amount": {
138
+ "type": "float",
139
+ "unit": "USDT0 tokens",
140
+ "description": "Amount of USDT0 to allocate to HyperLend.",
141
+ "minimum": 1.0, # TODO: 10
142
+ "examples": ["100.0", "250.5"],
143
+ },
144
+ "gas_token_amount": {
145
+ "type": "float",
146
+ "unit": "HYPE tokens",
147
+ "description": "Amount of HYPE to top up into the vault wallet to cover gas costs.",
148
+ "minimum": 0.0,
149
+ "maximum": GAS_MAXIMUM,
150
+ "recommended": GAS_MAXIMUM,
151
+ },
101
152
  },
153
+ "result": "USDT0 converted into the top-performing HyperLend stablecoin and supplied on-chain.",
154
+ },
155
+ "withdraw": {
156
+ "description": "Unwinds the position, converts balances to USDT0, and returns funds (plus HYPE buffer) to the main wallet.",
157
+ "parameters": {},
158
+ "result": "Principal and accrued gains returned in USDT0; residual HYPE buffer swept home.",
159
+ },
160
+ "update": {
161
+ "description": (
162
+ "Evaluates tournament projections and rotates when the hysteresis band is breached "
163
+ f"(dwell={HYSTERESIS_DWELL_HOURS}h, z={HYSTERESIS_Z:.2f}) or when a short-circuit gap is hit "
164
+ "(set HYPERLEND_ROTATION_POLICY=cooldown to restore the legacy threshold/cooldown rule)."
165
+ ),
166
+ "parameters": {},
167
+ },
168
+ "status": {
169
+ "description": "Summarises current lend position, APY, and chosen asset.",
170
+ "provides": [
171
+ "lent_asset",
172
+ "lent_balance",
173
+ "current_apy",
174
+ "best_candidate",
175
+ "best_candidate_apy",
176
+ ],
177
+ },
178
+ "points": {
179
+ "description": "Fetch the HyperLend points account snapshot for this vault wallet using a signed login.",
180
+ "parameters": {},
181
+ "result": "Returns the HyperLend points API payload for the strategy wallet.",
182
+ },
183
+ "technical_details": {
184
+ "rotation_policy": ROTATION_POLICY.lower(),
185
+ "hysteresis_dwell_hours": HYSTERESIS_DWELL_HOURS,
186
+ "hysteresis_z": HYSTERESIS_Z,
187
+ "rotation_tx_cost": ROTATION_TX_COST,
102
188
  },
103
- "result": "USDT0 converted into the top-performing HyperLend stablecoin and supplied on-chain.",
104
- },
105
- "withdraw": {
106
- "description": "Unwinds the position, converts balances to USDT0, and returns funds (plus HYPE buffer) to the main wallet.",
107
- "parameters": {},
108
- "result": "Principal and accrued gains returned in USDT0; residual HYPE buffer swept home.",
109
- },
110
- "update": {
111
- "description": (
112
- "Evaluates tournament projections and rotates when the hysteresis band is breached "
113
- f"(dwell={HYSTERESIS_DWELL_HOURS}h, z={HYSTERESIS_Z:.2f}) or when a short-circuit gap is hit "
114
- "(set HYPERLEND_ROTATION_POLICY=cooldown to restore the legacy threshold/cooldown rule)."
115
- ),
116
- "parameters": {},
117
- },
118
- "status": {
119
- "description": "Summarises current lend position, APY, and chosen asset.",
120
- "provides": [
121
- "lent_asset",
122
- "lent_balance",
123
- "current_apy",
124
- "best_candidate",
125
- "best_candidate_apy",
126
- ],
127
- },
128
- "points": {
129
- "description": "Fetch the HyperLend points account snapshot for this vault wallet using a signed login.",
130
- "parameters": {},
131
- "result": "Returns the HyperLend points API payload for the strategy wallet.",
132
- },
133
- "technical_details": {
134
- "rotation_policy": ROTATION_POLICY.lower(),
135
- "hysteresis_dwell_hours": HYSTERESIS_DWELL_HOURS,
136
- "hysteresis_z": HYSTERESIS_Z,
137
- "rotation_tx_cost": ROTATION_TX_COST,
138
189
  },
139
- }
190
+ )
140
191
 
141
192
  def __init__(
142
193
  self,
@@ -2323,6 +2374,17 @@ class HyperlendStableYieldStrategy(Strategy):
2323
2374
  }
2324
2375
 
2325
2376
  @staticmethod
2326
- def policies() -> list[str]:
2377
+ async def policies() -> list[str]:
2327
2378
  """Return policy strings used to scope on-chain permissions."""
2328
- return []
2379
+ return [
2380
+ any_hyperliquid_l1_payload(),
2381
+ any_hyperliquid_user_payload(),
2382
+ hypecore_sentinel_deposit(),
2383
+ await whype_deposit_and_withdraw(),
2384
+ erc20_spender_for_any_token(HYPERLEND_POOL),
2385
+ await hyperlend_supply_and_withdraw(),
2386
+ erc20_spender_for_any_token(ENSO_ROUTER),
2387
+ await enso_swap(),
2388
+ erc20_spender_for_any_token(PRJX_ROUTER),
2389
+ await prjx_swap(),
2390
+ ]
@@ -11,6 +11,14 @@ from wayfinder_paths.core.services.local_token_txn import (
11
11
  LocalTokenTxnService,
12
12
  )
13
13
  from wayfinder_paths.core.services.web3_service import DefaultWeb3Service
14
+ from wayfinder_paths.core.strategies.descriptors import (
15
+ Complexity,
16
+ Directionality,
17
+ Frequency,
18
+ StratDescriptor,
19
+ TokenExposure,
20
+ Volatility,
21
+ )
14
22
  from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
15
23
  from wayfinder_paths.core.wallets.WalletManager import WalletManager
16
24
  from wayfinder_paths.vaults.adapters.balance_adapter.adapter import BalanceAdapter
@@ -33,84 +41,113 @@ class StablecoinYieldStrategy(Strategy):
33
41
  SUPPORTED_NETWORK_CODES = {"base"}
34
42
  ROTATION_MIN_INTERVAL = timedelta(days=14)
35
43
  MINIMUM_APY_IMPROVEMENT = 0.01
36
- GAS_MAXIMUM = 0.02
37
-
38
- description = (
39
- "An automated yield optimization strategy that maximizes returns on USDC deposits on Base.\n\n"
40
- "What it does: Continuously scans and evaluates yield opportunities across Base-based DeFi protocols to find the "
41
- "highest-yielding, low-risk positions for USDC. Automatically rebalances positions when better opportunities "
42
- "emerge to maintain optimal yield generation.\n\n"
43
- "Exposure type: Stable USD-denominated exposure with minimal impermanent loss risk. Focuses exclusively on USDC "
44
- "and operations on the Base network to preserve capital and maximize yield.\n\n"
45
- "Chains: Operates solely on the Base network.\n\n"
46
- f"Deposit/Withdrawal: Accepts deposits only in USDC on Base with a minimum of {MIN_AMOUNT_USDC} USDC. Gas: Requires Base ETH "
47
- "for gas fees during position entry, rebalancing, and exit (~0.001-0.02 ETH per rebalance cycle). Strategy automatically "
48
- "deploys funds to an optimal yield farming position on Base. Withdrawals exit current positions and return USDC to the "
49
- "user wallet.\n\n"
50
- f"Risks: Primary risks include smart contract vulnerabilities in underlying Base DeFi protocols, temporary yield fluctuations, "
51
- f"gas costs during rebalancing, and potential brief capital lock-up during protocol transitions. Strategy filters for a minimum TVL of ${MIN_TVL:,}."
52
- )
53
- summary = (
54
- "Automated stablecoin yield farming across DeFi protocols on Base. "
55
- f"Continuously optimizes positions for maximum stable yield while avoiding impermanent loss. "
56
- f"Min: {MIN_AMOUNT_USDC} USDC + ETH gas. Filters for ${MIN_TVL:,}+ TVL protocols."
57
- )
58
-
59
- # config metadata for UIs/agents
60
- config = {
61
- "deposit": {
62
- "parameters": {
63
- "main_token_amount": {
64
- "type": "float",
65
- "description": "amount of Base USDC (token id: usd-coin-base) to deposit",
66
- },
67
- "gas_token_amount": {
68
- "type": "float",
69
- "description": "amount of Base ETH (token id: ethereum-base) to deposit for gas fees",
70
- "minimum": 0,
71
- "maximum": GAS_MAXIMUM,
44
+ GAS_MAXIMUM = 10e-4 # ethereum float
45
+ GAS_SAFETY_FRACTION = 1 / 3
46
+
47
+ INFO = StratDescriptor(
48
+ description=(
49
+ "An automated yield optimization strategy that maximizes returns on USDC deposits on Base.\n\n"
50
+ "What it does: Continuously scans and evaluates yield opportunities across Base-based DeFi protocols to find the "
51
+ "highest-yielding, low-risk positions for USDC. Automatically rebalances positions when better opportunities "
52
+ "emerge to maintain optimal yield generation.\n\n"
53
+ "Exposure type: Stable USD-denominated exposure with minimal impermanent loss risk. Focuses exclusively on USDC "
54
+ "and operations on the Base network to preserve capital and maximize yield.\n\n"
55
+ "Chains: Operates solely on the Base network.\n\n"
56
+ f"Deposit/Withdrawal: Accepts deposits only in USDC on Base with a minimum of {MIN_AMOUNT_USDC} USDC. Gas: Requires Base ETH "
57
+ "for gas fees during position entry, rebalancing, and exit (~0.001-0.02 ETH per rebalance cycle). Strategy automatically "
58
+ "deploys funds to an optimal yield farming position on Base. Withdrawals exit current positions and return USDC to the "
59
+ "user wallet.\n\n"
60
+ f"Risks: Primary risks include smart contract vulnerabilities in underlying Base DeFi protocols, temporary yield fluctuations, "
61
+ f"gas costs during rebalancing, and potential brief capital lock-up during protocol transitions. Strategy filters for a minimum TVL of ${MIN_TVL:,}."
62
+ ),
63
+ summary=(
64
+ "Automated stablecoin yield farming across DeFi protocols on Base. "
65
+ f"Continuously optimizes positions for maximum stable yield while avoiding impermanent loss. "
66
+ f"Min: {MIN_AMOUNT_USDC} USDC + ETH gas. Filters for ${MIN_TVL:,}+ TVL protocols."
67
+ ),
68
+ gas_token_symbol="ETH",
69
+ gas_token_id="ethereum-base",
70
+ deposit_token_id="usd-coin-base",
71
+ minimum_net_deposit=50,
72
+ gas_maximum=GAS_MAXIMUM,
73
+ # Anything below this level triggers a gas top-up
74
+ gas_threshold=GAS_MAXIMUM * GAS_SAFETY_FRACTION,
75
+ # risk indicators
76
+ volatility=Volatility.LOW,
77
+ volatility_description_short=(
78
+ "Capital sits in Base stablecoin lending pools, so price swings are minimal."
79
+ ),
80
+ directionality=Directionality.MARKET_NEUTRAL,
81
+ directionality_description=(
82
+ "Fully USD-denominated yield farming with no directional crypto beta."
83
+ ),
84
+ complexity=Complexity.LOW,
85
+ complexity_description="Agent handles optimal pool finding and rebalancing",
86
+ token_exposure=TokenExposure.STABLECOINS,
87
+ token_exposure_description=(
88
+ "Only Base USDC (and occasional stable swaps) with no volatile assets."
89
+ ),
90
+ frequency=Frequency.LOW,
91
+ frequency_description=(
92
+ "Updates every 2 hours; rebalances infrequent (bi-weekly cooldowns)."
93
+ ),
94
+ return_drivers=["pool yield"],
95
+ # config metadata for UIs/agents
96
+ config={
97
+ "deposit": {
98
+ "parameters": {
99
+ "main_token_amount": {
100
+ "type": "float",
101
+ "description": "amount of Base USDC (token id: usd-coin-base) to deposit",
102
+ },
103
+ "gas_token_amount": {
104
+ "type": "float",
105
+ "description": "amount of Base ETH (token id: ethereum-base) to deposit for gas fees",
106
+ "minimum": 0,
107
+ "maximum": GAS_MAXIMUM,
108
+ },
72
109
  },
110
+ "process": "Deposits USDC on Base and searches for the highest yield opportunities among Base-based DeFi protocols",
111
+ "requirements": [
112
+ "Sufficient USDC balance on Base",
113
+ "Base ETH available for gas",
114
+ ],
115
+ "result": "Funds deployed to a yield farming position on Base",
116
+ },
117
+ "withdraw": {
118
+ "parameters": {},
119
+ "process": "Exits yield positions on Base and returns USDC to the user wallet",
120
+ "requirements": [
121
+ "Active positions to exit",
122
+ "Gas for transactions on Base",
123
+ ],
124
+ "result": "USDC returned to wallet and positions closed on Base",
125
+ },
126
+ "update": {
127
+ "parameters": {},
128
+ "process": "Scans for better yield opportunities on Base and rebalances positions automatically",
129
+ "frequency": "Call daily or when significant yield changes occur",
130
+ "requirements": [
131
+ "Active strategy positions on Base",
132
+ "Sufficient Base gas for rebalancing",
133
+ ],
134
+ "result": "Positions optimized for maximum yield on Base",
135
+ },
136
+ "technical_details": {
137
+ "wallet_structure": "Uses strategy subwallet for isolation",
138
+ "chains": ["Base"],
139
+ "protocols": ["Various Base DeFi yield protocols"],
140
+ "tokens": ["USDC"],
141
+ "gas_requirements": "~0.001-0.02 ETH per rebalance on Base",
142
+ "search_depth": SEARCH_DEPTH,
143
+ "minimum_tvl": MIN_TVL,
144
+ "dust_apy_threshold": DUST_APY,
145
+ "minimum_apy_edge": MINIMUM_APY_IMPROVEMENT,
146
+ "rotation_cooldown_days": ROTATION_MIN_INTERVAL.days,
147
+ "profit_horizon_days": MINIMUM_DAYS_UNTIL_PROFIT,
73
148
  },
74
- "process": "Deposits USDC on Base and searches for the highest yield opportunities among Base-based DeFi protocols",
75
- "requirements": [
76
- "Sufficient USDC balance on Base",
77
- "Base ETH available for gas",
78
- ],
79
- "result": "Funds deployed to a yield farming position on Base",
80
- },
81
- "withdraw": {
82
- "parameters": {},
83
- "process": "Exits yield positions on Base and returns USDC to the user wallet",
84
- "requirements": [
85
- "Active positions to exit",
86
- "Gas for transactions on Base",
87
- ],
88
- "result": "USDC returned to wallet and positions closed on Base",
89
- },
90
- "update": {
91
- "parameters": {},
92
- "process": "Scans for better yield opportunities on Base and rebalances positions automatically",
93
- "frequency": "Call daily or when significant yield changes occur",
94
- "requirements": [
95
- "Active strategy positions on Base",
96
- "Sufficient Base gas for rebalancing",
97
- ],
98
- "result": "Positions optimized for maximum yield on Base",
99
- },
100
- "technical_details": {
101
- "wallet_structure": "Uses strategy subwallet for isolation",
102
- "chains": ["Base"],
103
- "protocols": ["Various Base DeFi yield protocols"],
104
- "tokens": ["USDC"],
105
- "gas_requirements": "~0.001-0.02 ETH per rebalance on Base",
106
- "search_depth": SEARCH_DEPTH,
107
- "minimum_tvl": MIN_TVL,
108
- "dust_apy_threshold": DUST_APY,
109
- "minimum_apy_edge": MINIMUM_APY_IMPROVEMENT,
110
- "rotation_cooldown_days": ROTATION_MIN_INTERVAL.days,
111
- "profit_horizon_days": MINIMUM_DAYS_UNTIL_PROFIT,
112
149
  },
113
- }
150
+ )
114
151
 
115
152
  def __init__(
116
153
  self,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wayfinder-paths
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: Wayfinder Path: strategies and adapters
5
5
  Author: Wayfinder
6
6
  Author-email: dev@wayfinder.ai
@@ -647,55 +647,27 @@ poetry run python wayfinder_paths/run_strategy.py stablecoin_yield_strategy --co
647
647
 
648
648
  ## 📦 Publishing
649
649
 
650
- This package is published to [PyPI](https://pypi.org/project/wayfinder-paths/) (Python Package Index).
651
-
652
- ### How PyPI Works
653
-
654
- - **Public by default**: Once published, anyone can download and install your package with `pip install wayfinder-paths` (no authentication required)
655
- - **Who can update**: Only package owners and maintainers can publish new versions
656
- - **Version control**: Version numbers must be unique and incrementing (you cannot overwrite a published version)
657
- - **Access control**: You control who can publish by adding collaborators on PyPI (project owners can add maintainers)
658
-
659
- ### Publishing a New Version
660
-
661
- 1. **Update the version** in `pyproject.toml`:
662
- ```toml
663
- [tool.poetry]
664
- version = "0.1.2" # Must be higher than previous version
665
- ```
666
-
667
- 2. **Set your PyPI token**:
668
- ```bash
669
- export PUBLISH_TOKEN="your_pypi_token_here"
670
- # Or add to .env file: PUBLISH_TOKEN=your_pypi_token_here
671
- ```
672
-
673
- Get your PyPI token from: https://pypi.org/manage/account/token/
674
-
675
- **Note**: PyPI requires 2FA (two-factor authentication) for all accounts.
676
-
677
- 3. **Publish**:
678
- ```bash
679
- just publish
680
- ```
681
-
682
- This will:
683
- - Build the package (wheel and source distribution)
684
- - Publish to PyPI
685
- - Make it publicly available for installation
686
-
687
- ### Installing the Published Package
688
-
689
- Anyone can install the published package with:
650
+ Publish to PyPI:
651
+
690
652
  ```bash
691
- pip install wayfinder-paths
653
+ export PUBLISH_TOKEN="your_pypi_token"
654
+ just publish
692
655
  ```
693
656
 
694
- Or with Poetry:
657
+ Install the published package:
658
+
695
659
  ```bash
660
+ pip install wayfinder-paths
661
+ # or
696
662
  poetry add wayfinder-paths
697
663
  ```
698
664
 
665
+ Install from Git (development):
666
+
667
+ ```bash
668
+ pip install git+https://github.com/wayfinder-ai/wayfinder-paths.git
669
+ ```
670
+
699
671
  ### Managing Package Access
700
672
 
701
673
  To add collaborators who can publish updates: