wayfinder-paths 0.1.10__tar.gz → 0.1.11__tar.gz
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-0.1.10 → wayfinder_paths-0.1.11}/PKG-INFO +7 -7
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/README.md +6 -6
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/pyproject.toml +1 -1
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/services/base.py +0 -55
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/services/local_evm_txn.py +15 -130
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/utils/evm_helpers.py +0 -27
- wayfinder_paths-0.1.10/wayfinder_paths/CONFIG_GUIDE.md +0 -390
- wayfinder_paths-0.1.10/wayfinder_paths/config.example.json +0 -22
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/LICENSE +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/abis/generic/erc20.json +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/balance_adapter/README.md +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/balance_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/balance_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/balance_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/brap_adapter/README.md +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/brap_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/brap_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/brap_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/brap_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/hyperlend_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/hyperlend_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/hyperliquid_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/hyperliquid_adapter/executor.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/hyperliquid_adapter/utils.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/ledger_adapter/README.md +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/ledger_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/ledger_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/ledger_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/ledger_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/moonwell_adapter/README.md +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/moonwell_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/moonwell_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/pool_adapter/README.md +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/pool_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/pool_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/pool_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/pool_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/token_adapter/README.md +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/token_adapter/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/token_adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/token_adapter/examples.json +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/adapters/token_adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/conftest.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/adapters/BaseAdapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/adapters/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/adapters/base.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/adapters/models.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/analytics/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/analytics/bootstrap.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/analytics/stats.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/analytics/test_analytics.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/clients/AuthClient.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/clients/BRAPClient.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/clients/ClientManager.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/clients/HyperlendClient.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/clients/LedgerClient.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/clients/PoolClient.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/clients/TokenClient.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/clients/WalletClient.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/clients/WayfinderClient.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/clients/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/clients/protocols.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/clients/sdk_example.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/config.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/constants/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/constants/base.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/constants/erc20_abi.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/constants/hyperlend_abi.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/constants/moonwell_abi.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/engine/StrategyJob.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/engine/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/services/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/services/local_token_txn.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/services/web3_service.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/settings.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/strategies/Strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/strategies/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/strategies/base.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/strategies/descriptors.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/utils/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/utils/wallets.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/wallets/README.md +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/wallets/WalletManager.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/wallets/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/policies/enso.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/policies/erc20.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/policies/evm.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/policies/hyper_evm.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/policies/hyperlend.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/policies/hyperliquid.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/policies/moonwell.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/policies/prjx.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/policies/util.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/run_strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/scripts/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/scripts/create_strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/scripts/make_wallets.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/scripts/run_strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/basis_trading_strategy/README.md +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/basis_trading_strategy/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/basis_trading_strategy/constants.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/basis_trading_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/basis_trading_strategy/snapshot_mixin.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/basis_trading_strategy/strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/basis_trading_strategy/types.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/config.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/README.md +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/stablecoin_yield_strategy/examples.json +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/templates/adapter/README.md +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/templates/adapter/adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/templates/adapter/examples.json +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/templates/adapter/test_adapter.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/templates/strategy/README.md +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/templates/strategy/examples.json +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/templates/strategy/strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/templates/strategy/test_strategy.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/tests/__init__.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/tests/test_smoke_manifest.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/tests/test_test_coverage.py +0 -0
- {wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: wayfinder-paths
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.11
|
|
4
4
|
Summary: Wayfinder Path: strategies and adapters
|
|
5
5
|
Author: Wayfinder
|
|
6
6
|
Author-email: dev@wayfinder.ai
|
|
@@ -48,7 +48,7 @@ just create-wallets
|
|
|
48
48
|
# Or manually: poetry run python wayfinder_paths/scripts/make_wallets.py -n 1
|
|
49
49
|
|
|
50
50
|
# To test a specific strategy
|
|
51
|
-
just
|
|
51
|
+
just create-wallet stablecoin_yield_strategy
|
|
52
52
|
|
|
53
53
|
# Copy and configure
|
|
54
54
|
cp wayfinder_paths/config.example.json config.json
|
|
@@ -374,11 +374,11 @@ class MyStrategy(Strategy):
|
|
|
374
374
|
|
|
375
375
|
The following strategies are available and can be run using the CLI:
|
|
376
376
|
|
|
377
|
-
| Strategy
|
|
378
|
-
|
|
379
|
-
| `basis_trading_strategy`
|
|
380
|
-
| `hyperlend_stable_yield_strategy` | Stable yield on HyperLend
|
|
381
|
-
| `moonwell_wsteth_loop_strategy`
|
|
377
|
+
| Strategy | Description | Chain |
|
|
378
|
+
| --------------------------------- | --------------------------- | -------- |
|
|
379
|
+
| `basis_trading_strategy` | Delta-neutral basis trading | - |
|
|
380
|
+
| `hyperlend_stable_yield_strategy` | Stable yield on HyperLend | HyperEVM |
|
|
381
|
+
| `moonwell_wsteth_loop_strategy` | Leveraged wstETH yield loop | Base |
|
|
382
382
|
|
|
383
383
|
#### Running Strategies
|
|
384
384
|
|
|
@@ -25,7 +25,7 @@ just create-wallets
|
|
|
25
25
|
# Or manually: poetry run python wayfinder_paths/scripts/make_wallets.py -n 1
|
|
26
26
|
|
|
27
27
|
# To test a specific strategy
|
|
28
|
-
just
|
|
28
|
+
just create-wallet stablecoin_yield_strategy
|
|
29
29
|
|
|
30
30
|
# Copy and configure
|
|
31
31
|
cp wayfinder_paths/config.example.json config.json
|
|
@@ -351,11 +351,11 @@ class MyStrategy(Strategy):
|
|
|
351
351
|
|
|
352
352
|
The following strategies are available and can be run using the CLI:
|
|
353
353
|
|
|
354
|
-
| Strategy
|
|
355
|
-
|
|
356
|
-
| `basis_trading_strategy`
|
|
357
|
-
| `hyperlend_stable_yield_strategy` | Stable yield on HyperLend
|
|
358
|
-
| `moonwell_wsteth_loop_strategy`
|
|
354
|
+
| Strategy | Description | Chain |
|
|
355
|
+
| --------------------------------- | --------------------------- | -------- |
|
|
356
|
+
| `basis_trading_strategy` | Delta-neutral basis trading | - |
|
|
357
|
+
| `hyperlend_stable_yield_strategy` | Stable yield on HyperLend | HyperEVM |
|
|
358
|
+
| `moonwell_wsteth_loop_strategy` | Leveraged wstETH yield loop | Base |
|
|
359
359
|
|
|
360
360
|
#### Running Strategies
|
|
361
361
|
|
|
@@ -50,61 +50,6 @@ class EvmTxn(ABC):
|
|
|
50
50
|
transaction confirmations.
|
|
51
51
|
"""
|
|
52
52
|
|
|
53
|
-
@abstractmethod
|
|
54
|
-
async def get_balance(
|
|
55
|
-
self,
|
|
56
|
-
address: str,
|
|
57
|
-
token_address: str | None,
|
|
58
|
-
chain_id: int,
|
|
59
|
-
block_identifier: int | str | None = None,
|
|
60
|
-
) -> tuple[bool, Any]:
|
|
61
|
-
"""
|
|
62
|
-
Get balance for an address at a specific block.
|
|
63
|
-
|
|
64
|
-
Args:
|
|
65
|
-
address: Address to query balance for
|
|
66
|
-
token_address: ERC20 token address, or None for native token
|
|
67
|
-
chain_id: Chain ID
|
|
68
|
-
block_identifier: Block to query at. Can be:
|
|
69
|
-
- int: specific block number (for pinning to tx block)
|
|
70
|
-
- "safe": OP Stack safe block (data posted to L1)
|
|
71
|
-
- "finalized": fully finalized block
|
|
72
|
-
- None/"latest": current head (default, but avoid after txs)
|
|
73
|
-
|
|
74
|
-
Returns:
|
|
75
|
-
Tuple of (success, balance_integer_or_error_message)
|
|
76
|
-
"""
|
|
77
|
-
pass
|
|
78
|
-
|
|
79
|
-
@abstractmethod
|
|
80
|
-
async def approve_token(
|
|
81
|
-
self,
|
|
82
|
-
token_address: str,
|
|
83
|
-
spender: str,
|
|
84
|
-
amount: int,
|
|
85
|
-
from_address: str,
|
|
86
|
-
chain_id: int,
|
|
87
|
-
wait_for_receipt: bool = True,
|
|
88
|
-
timeout: int = DEFAULT_TRANSACTION_TIMEOUT,
|
|
89
|
-
) -> tuple[bool, Any]:
|
|
90
|
-
"""
|
|
91
|
-
Approve a spender to spend tokens on behalf of from_address.
|
|
92
|
-
|
|
93
|
-
Args:
|
|
94
|
-
token_address: ERC20 token contract address
|
|
95
|
-
spender: Address being approved to spend tokens
|
|
96
|
-
amount: Amount to approve (in token units, not human-readable)
|
|
97
|
-
from_address: Address approving the tokens
|
|
98
|
-
chain_id: Chain ID
|
|
99
|
-
wait_for_receipt: Whether to wait for the transaction receipt
|
|
100
|
-
timeout: Receipt timeout in seconds
|
|
101
|
-
|
|
102
|
-
Returns:
|
|
103
|
-
Tuple of (success, transaction_result_dict_or_error_message)
|
|
104
|
-
Transaction result should include 'tx_hash' and optionally 'receipt'
|
|
105
|
-
"""
|
|
106
|
-
pass
|
|
107
|
-
|
|
108
53
|
@abstractmethod
|
|
109
54
|
async def broadcast_transaction(
|
|
110
55
|
self,
|
{wayfinder_paths-0.1.10 → wayfinder_paths-0.1.11}/wayfinder_paths/core/services/local_evm_txn.py
RENAMED
|
@@ -4,16 +4,9 @@ from typing import Any
|
|
|
4
4
|
from eth_account import Account
|
|
5
5
|
from eth_utils import to_checksum_address
|
|
6
6
|
from loguru import logger
|
|
7
|
-
from web3 import AsyncHTTPProvider, AsyncWeb3
|
|
7
|
+
from web3 import AsyncHTTPProvider, AsyncWeb3
|
|
8
8
|
|
|
9
|
-
from wayfinder_paths.core.constants import (
|
|
10
|
-
ZERO_ADDRESS,
|
|
11
|
-
)
|
|
12
9
|
from wayfinder_paths.core.constants.base import DEFAULT_TRANSACTION_TIMEOUT
|
|
13
|
-
from wayfinder_paths.core.constants.erc20_abi import (
|
|
14
|
-
ERC20_APPROVAL_ABI,
|
|
15
|
-
ERC20_MINIMAL_ABI,
|
|
16
|
-
)
|
|
17
10
|
from wayfinder_paths.core.services.base import EvmTxn
|
|
18
11
|
from wayfinder_paths.core.utils.evm_helpers import (
|
|
19
12
|
resolve_private_key_for_from_address,
|
|
@@ -60,105 +53,12 @@ class LocalEvmTxn(EvmTxn):
|
|
|
60
53
|
def __init__(self, config: dict[str, Any] | None = None):
|
|
61
54
|
self.config = config or {}
|
|
62
55
|
self.logger = logger.bind(provider="LocalWalletProvider")
|
|
63
|
-
# Cache web3 instances per chain to avoid load balancer inconsistency
|
|
64
|
-
self._web3_cache: dict[int, AsyncWeb3] = {}
|
|
65
56
|
|
|
66
57
|
def get_web3(self, chain_id: int) -> AsyncWeb3:
|
|
67
|
-
# Reuse cached instance to ensure consistent RPC node for reads after writes
|
|
68
|
-
if chain_id in self._web3_cache:
|
|
69
|
-
return self._web3_cache[chain_id]
|
|
70
58
|
rpc_url = self._resolve_rpc_url(chain_id)
|
|
71
59
|
w3 = AsyncWeb3(AsyncHTTPProvider(rpc_url))
|
|
72
|
-
self._web3_cache[chain_id] = w3
|
|
73
60
|
return w3
|
|
74
61
|
|
|
75
|
-
async def get_balance(
|
|
76
|
-
self,
|
|
77
|
-
address: str,
|
|
78
|
-
token_address: str | None,
|
|
79
|
-
chain_id: int,
|
|
80
|
-
block_identifier: int | str | None = None,
|
|
81
|
-
) -> tuple[bool, Any]:
|
|
82
|
-
"""
|
|
83
|
-
Get balance for an address at a specific block.
|
|
84
|
-
|
|
85
|
-
Args:
|
|
86
|
-
address: Address to query balance for
|
|
87
|
-
token_address: ERC20 token address, or None for native token
|
|
88
|
-
chain_id: Chain ID
|
|
89
|
-
block_identifier: Block to query at. Can be:
|
|
90
|
-
- int: specific block number (for pinning to tx block)
|
|
91
|
-
- "safe": OP Stack safe block (data posted to L1)
|
|
92
|
-
- "finalized": fully finalized block
|
|
93
|
-
- None/"latest": current head (default, but avoid after txs)
|
|
94
|
-
|
|
95
|
-
Returns:
|
|
96
|
-
Tuple of (success, balance_integer_or_error_message)
|
|
97
|
-
"""
|
|
98
|
-
w3 = self.get_web3(chain_id)
|
|
99
|
-
try:
|
|
100
|
-
checksum_addr = to_checksum_address(address)
|
|
101
|
-
block_id = block_identifier if block_identifier is not None else "latest"
|
|
102
|
-
|
|
103
|
-
if not token_address or token_address.lower() == ZERO_ADDRESS:
|
|
104
|
-
balance = await w3.eth.get_balance(
|
|
105
|
-
checksum_addr, block_identifier=block_id
|
|
106
|
-
)
|
|
107
|
-
return (True, int(balance))
|
|
108
|
-
|
|
109
|
-
token_checksum = to_checksum_address(token_address)
|
|
110
|
-
contract = w3.eth.contract(address=token_checksum, abi=ERC20_MINIMAL_ABI)
|
|
111
|
-
balance = await contract.functions.balanceOf(checksum_addr).call(
|
|
112
|
-
block_identifier=block_id
|
|
113
|
-
)
|
|
114
|
-
return (True, int(balance))
|
|
115
|
-
|
|
116
|
-
except Exception as exc: # noqa: BLE001
|
|
117
|
-
self.logger.error(f"Failed to get balance: {exc}")
|
|
118
|
-
return (False, f"Balance query failed: {exc}")
|
|
119
|
-
finally:
|
|
120
|
-
await self._close_web3(w3)
|
|
121
|
-
|
|
122
|
-
async def approve_token(
|
|
123
|
-
self,
|
|
124
|
-
token_address: str,
|
|
125
|
-
spender: str,
|
|
126
|
-
amount: int,
|
|
127
|
-
from_address: str,
|
|
128
|
-
chain_id: int,
|
|
129
|
-
wait_for_receipt: bool = True,
|
|
130
|
-
timeout: int = DEFAULT_TRANSACTION_TIMEOUT,
|
|
131
|
-
) -> tuple[bool, Any]:
|
|
132
|
-
try:
|
|
133
|
-
token_checksum = to_checksum_address(token_address)
|
|
134
|
-
spender_checksum = to_checksum_address(spender)
|
|
135
|
-
from_checksum = to_checksum_address(from_address)
|
|
136
|
-
amount_int = int(amount)
|
|
137
|
-
|
|
138
|
-
w3_sync = Web3()
|
|
139
|
-
contract = w3_sync.eth.contract(
|
|
140
|
-
address=token_checksum, abi=ERC20_APPROVAL_ABI
|
|
141
|
-
)
|
|
142
|
-
transaction_data = contract.encode_abi(
|
|
143
|
-
"approve", args=[spender_checksum, amount_int]
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
approve_txn = {
|
|
147
|
-
"from": from_checksum,
|
|
148
|
-
"chainId": int(chain_id),
|
|
149
|
-
"to": token_checksum,
|
|
150
|
-
"data": transaction_data,
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return await self.broadcast_transaction(
|
|
154
|
-
approve_txn,
|
|
155
|
-
wait_for_receipt=wait_for_receipt,
|
|
156
|
-
timeout=timeout,
|
|
157
|
-
)
|
|
158
|
-
except Exception as exc: # noqa: BLE001
|
|
159
|
-
self.logger.error(f"ERC20 approval failed: {exc}")
|
|
160
|
-
return (False, f"ERC20 approval failed: {exc}")
|
|
161
|
-
|
|
162
62
|
def _validate_transaction(self, transaction: dict[str, Any]) -> dict[str, Any]:
|
|
163
63
|
tx = dict(transaction)
|
|
164
64
|
|
|
@@ -264,29 +164,29 @@ class LocalEvmTxn(EvmTxn):
|
|
|
264
164
|
*,
|
|
265
165
|
wait_for_receipt: bool = True,
|
|
266
166
|
timeout: int = DEFAULT_TRANSACTION_TIMEOUT,
|
|
267
|
-
confirmations: int =
|
|
167
|
+
confirmations: int = 1,
|
|
268
168
|
) -> tuple[bool, Any]:
|
|
269
169
|
try:
|
|
270
170
|
chain_id = transaction["chainId"]
|
|
271
171
|
from_address = transaction["from"]
|
|
272
172
|
|
|
273
|
-
|
|
173
|
+
web3 = self.get_web3(chain_id)
|
|
274
174
|
try:
|
|
275
175
|
transaction = self._validate_transaction(transaction)
|
|
276
|
-
transaction = await self._nonce_transaction(transaction,
|
|
277
|
-
transaction = await self._gas_limit_transaction(transaction,
|
|
176
|
+
transaction = await self._nonce_transaction(transaction, web3)
|
|
177
|
+
transaction = await self._gas_limit_transaction(transaction, web3)
|
|
278
178
|
transaction = await self._gas_price_transaction(
|
|
279
|
-
transaction, chain_id,
|
|
179
|
+
transaction, chain_id, web3
|
|
280
180
|
)
|
|
281
181
|
|
|
282
182
|
signed_tx = self._sign_transaction(transaction, from_address)
|
|
283
183
|
|
|
284
|
-
tx_hash = await
|
|
184
|
+
tx_hash = await web3.eth.send_raw_transaction(signed_tx)
|
|
285
185
|
tx_hash_hex = tx_hash.hex()
|
|
286
186
|
|
|
287
187
|
result: dict[str, Any] = {"tx_hash": tx_hash_hex}
|
|
288
188
|
if wait_for_receipt:
|
|
289
|
-
receipt = await
|
|
189
|
+
receipt = await web3.eth.wait_for_transaction_receipt(
|
|
290
190
|
tx_hash, timeout=timeout
|
|
291
191
|
)
|
|
292
192
|
result["receipt"] = self._format_receipt(receipt)
|
|
@@ -299,32 +199,19 @@ class LocalEvmTxn(EvmTxn):
|
|
|
299
199
|
False,
|
|
300
200
|
f"Transaction reverted (status={receipt_status}): {tx_hash_hex}",
|
|
301
201
|
)
|
|
302
|
-
# Check if transaction reverted (status=0)
|
|
303
|
-
# Handle both dict-like and attribute access for web3.py receipts
|
|
304
|
-
receipt_status = (
|
|
305
|
-
receipt.get("status")
|
|
306
|
-
if hasattr(receipt, "get")
|
|
307
|
-
else getattr(receipt, "status", None)
|
|
308
|
-
)
|
|
309
|
-
self.logger.debug(
|
|
310
|
-
f"Transaction {tx_hash_hex} receipt status: {receipt_status} (type: {type(receipt_status).__name__})"
|
|
311
|
-
)
|
|
312
|
-
if receipt_status == 0:
|
|
313
|
-
self.logger.error(f"Transaction reverted: {tx_hash_hex}")
|
|
314
|
-
return (False, f"Transaction reverted: {tx_hash_hex}")
|
|
315
202
|
|
|
316
203
|
# Wait for additional confirmations if requested
|
|
317
204
|
if confirmations > 0:
|
|
318
205
|
tx_block = result["receipt"].get("blockNumber")
|
|
319
206
|
if tx_block:
|
|
320
207
|
await self._wait_for_confirmations(
|
|
321
|
-
|
|
208
|
+
web3, tx_block, confirmations
|
|
322
209
|
)
|
|
323
210
|
|
|
324
211
|
return (True, result)
|
|
325
212
|
|
|
326
213
|
finally:
|
|
327
|
-
await self._close_web3(
|
|
214
|
+
await self._close_web3(web3)
|
|
328
215
|
|
|
329
216
|
except Exception as exc: # noqa: BLE001
|
|
330
217
|
self.logger.error(f"Transaction broadcast failed: {exc}")
|
|
@@ -362,14 +249,12 @@ class LocalEvmTxn(EvmTxn):
|
|
|
362
249
|
def _resolve_rpc_url(self, chain_id: int) -> str:
|
|
363
250
|
return resolve_rpc_url(chain_id, self.config or {}, None)
|
|
364
251
|
|
|
365
|
-
async def _close_web3(self,
|
|
366
|
-
# Don't close cached connections - we want to reuse them for consistency
|
|
367
|
-
if w3 in self._web3_cache.values():
|
|
368
|
-
return
|
|
252
|
+
async def _close_web3(self, web3: AsyncWeb3) -> None:
|
|
369
253
|
try:
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
254
|
+
if hasattr(web3.provider, "disconnect"):
|
|
255
|
+
await web3.provider.disconnect()
|
|
256
|
+
except Exception as e: # noqa: BLE001
|
|
257
|
+
self.logger.debug(f"Error disconnecting provider: {e}")
|
|
373
258
|
|
|
374
259
|
async def _wait_for_confirmations(
|
|
375
260
|
self, w3: AsyncWeb3, tx_block: int, confirmations: int
|
|
@@ -11,7 +11,6 @@ from pathlib import Path
|
|
|
11
11
|
from typing import Any
|
|
12
12
|
|
|
13
13
|
from loguru import logger
|
|
14
|
-
from web3 import AsyncHTTPProvider, AsyncWeb3
|
|
15
14
|
|
|
16
15
|
from wayfinder_paths.core.constants.base import CHAIN_CODE_TO_ID
|
|
17
16
|
|
|
@@ -86,32 +85,6 @@ def resolve_rpc_url(
|
|
|
86
85
|
raise ValueError("RPC URL not provided. Set strategy.rpc_urls in config.json.")
|
|
87
86
|
|
|
88
87
|
|
|
89
|
-
async def get_next_nonce(
|
|
90
|
-
from_address: str, rpc_url: str, use_latest: bool = False
|
|
91
|
-
) -> int:
|
|
92
|
-
"""
|
|
93
|
-
Get the next nonce for the given address.
|
|
94
|
-
|
|
95
|
-
Args:
|
|
96
|
-
from_address: Address to get nonce for
|
|
97
|
-
rpc_url: RPC URL to connect to
|
|
98
|
-
use_latest: If True, use 'latest' block instead of 'pending'
|
|
99
|
-
|
|
100
|
-
Returns:
|
|
101
|
-
Next nonce as integer
|
|
102
|
-
"""
|
|
103
|
-
w3 = AsyncWeb3(AsyncHTTPProvider(rpc_url))
|
|
104
|
-
try:
|
|
105
|
-
if use_latest:
|
|
106
|
-
return await w3.eth.get_transaction_count(from_address, "latest")
|
|
107
|
-
return await w3.eth.get_transaction_count(from_address)
|
|
108
|
-
finally:
|
|
109
|
-
try:
|
|
110
|
-
await w3.provider.session.close()
|
|
111
|
-
except Exception:
|
|
112
|
-
pass
|
|
113
|
-
|
|
114
|
-
|
|
115
88
|
def resolve_private_key_for_from_address(
|
|
116
89
|
from_address: str, config: dict[str, Any]
|
|
117
90
|
) -> str | None:
|