olas-operate-middleware 0.10.19__tar.gz → 0.11.0__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.
Files changed (101) hide show
  1. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/PKG-INFO +3 -1
  2. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/bridge/bridge_manager.py +10 -12
  3. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/bridge/providers/lifi_provider.py +5 -4
  4. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/bridge/providers/native_bridge_provider.py +6 -5
  5. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/bridge/providers/provider.py +22 -87
  6. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/bridge/providers/relay_provider.py +5 -4
  7. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/cli.py +446 -168
  8. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/constants.py +22 -2
  9. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/keys.py +13 -0
  10. olas_operate_middleware-0.11.0/operate/ledger/__init__.py +206 -0
  11. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/ledger/profiles.py +79 -11
  12. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/operate_types.py +205 -2
  13. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/quickstart/run_service.py +6 -10
  14. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/services/agent_runner.py +5 -3
  15. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/services/deployment_runner.py +3 -0
  16. olas_operate_middleware-0.11.0/operate/services/funding_manager.py +904 -0
  17. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/services/health_checker.py +4 -4
  18. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/services/manage.py +183 -310
  19. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/services/protocol.py +392 -140
  20. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/services/service.py +81 -5
  21. olas_operate_middleware-0.11.0/operate/settings.py +70 -0
  22. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/utils/__init__.py +0 -29
  23. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/utils/gnosis.py +79 -24
  24. olas_operate_middleware-0.11.0/operate/utils/single_instance.py +226 -0
  25. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/wallet/master.py +221 -181
  26. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/wallet/wallet_recovery_manager.py +5 -5
  27. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/pyproject.toml +3 -1
  28. olas_operate_middleware-0.10.19/operate/ledger/__init__.py +0 -101
  29. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/LICENSE +0 -0
  30. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/README.md +0 -0
  31. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/__init__.py +0 -0
  32. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/account/__init__.py +0 -0
  33. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/account/user.py +0 -0
  34. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/README.md +0 -0
  35. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/__init__.py +0 -0
  36. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/__init__.py +0 -0
  37. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/dual_staking_token/__init__.py +0 -0
  38. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/dual_staking_token/build/DualStakingToken.json +0 -0
  39. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/dual_staking_token/contract.py +0 -0
  40. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/dual_staking_token/contract.yaml +0 -0
  41. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/foreign_omnibridge/__init__.py +0 -0
  42. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/foreign_omnibridge/build/ForeignOmnibridge.json +0 -0
  43. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/foreign_omnibridge/contract.py +0 -0
  44. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/foreign_omnibridge/contract.yaml +0 -0
  45. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/home_omnibridge/__init__.py +0 -0
  46. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/home_omnibridge/build/HomeOmnibridge.json +0 -0
  47. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/home_omnibridge/contract.py +0 -0
  48. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/home_omnibridge/contract.yaml +0 -0
  49. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/l1_standard_bridge/__init__.py +0 -0
  50. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/l1_standard_bridge/build/L1StandardBridge.json +0 -0
  51. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/l1_standard_bridge/contract.py +0 -0
  52. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/l1_standard_bridge/contract.yaml +0 -0
  53. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/l2_standard_bridge/__init__.py +0 -0
  54. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/l2_standard_bridge/build/L2StandardBridge.json +0 -0
  55. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/l2_standard_bridge/contract.py +0 -0
  56. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/l2_standard_bridge/contract.yaml +0 -0
  57. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/mech_activity/__init__.py +0 -0
  58. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/mech_activity/build/MechActivity.json +0 -0
  59. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/mech_activity/contract.py +0 -0
  60. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/mech_activity/contract.yaml +0 -0
  61. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/optimism_mintable_erc20/__init__.py +0 -0
  62. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/optimism_mintable_erc20/build/OptimismMintableERC20.json +0 -0
  63. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/optimism_mintable_erc20/contract.py +0 -0
  64. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/optimism_mintable_erc20/contract.yaml +0 -0
  65. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/recovery_module/__init__.py +0 -0
  66. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/recovery_module/build/RecoveryModule.json +0 -0
  67. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/recovery_module/contract.py +0 -0
  68. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/recovery_module/contract.yaml +0 -0
  69. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/requester_activity_checker/__init__.py +0 -0
  70. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/requester_activity_checker/build/RequesterActivityChecker.json +0 -0
  71. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/requester_activity_checker/contract.py +0 -0
  72. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/requester_activity_checker/contract.yaml +0 -0
  73. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/staking_token/__init__.py +0 -0
  74. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/staking_token/build/StakingToken.json +0 -0
  75. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/staking_token/contract.py +0 -0
  76. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/staking_token/contract.yaml +0 -0
  77. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/uniswap_v2_erc20/__init__.py +0 -0
  78. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/uniswap_v2_erc20/build/IUniswapV2ERC20.json +0 -0
  79. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/uniswap_v2_erc20/contract.py +0 -0
  80. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/uniswap_v2_erc20/contract.yaml +0 -0
  81. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/uniswap_v2_erc20/tests/__init__.py +0 -0
  82. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/data/contracts/uniswap_v2_erc20/tests/test_contract.py +0 -0
  83. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/migration.py +0 -0
  84. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/operate_http/__init__.py +0 -0
  85. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/operate_http/exceptions.py +0 -0
  86. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/pearl.py +0 -0
  87. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/quickstart/analyse_logs.py +0 -0
  88. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/quickstart/claim_staking_rewards.py +0 -0
  89. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/quickstart/reset_configs.py +0 -0
  90. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/quickstart/reset_password.py +0 -0
  91. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/quickstart/reset_staking.py +0 -0
  92. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/quickstart/stop_service.py +0 -0
  93. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/quickstart/terminate_on_chain_service.py +0 -0
  94. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/quickstart/utils.py +0 -0
  95. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/resource.py +0 -0
  96. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/services/__init__.py +0 -0
  97. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/services/utils/__init__.py +0 -0
  98. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/services/utils/mech.py +0 -0
  99. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/services/utils/tendermint.py +0 -0
  100. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/utils/ssl.py +0 -0
  101. {olas_operate_middleware-0.10.19 → olas_operate_middleware-0.11.0}/operate/wallet/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: olas-operate-middleware
3
- Version: 0.10.19
3
+ Version: 0.11.0
4
4
  Summary:
5
5
  License-File: LICENSE
6
6
  Author: David Vilela
@@ -30,6 +30,7 @@ Requires-Dist: halo (==0.0.31)
30
30
  Requires-Dist: hexbytes (==0.3.1)
31
31
  Requires-Dist: ipfshttpclient (==0.8.0a2)
32
32
  Requires-Dist: jsonschema (==4.3.3)
33
+ Requires-Dist: multiaddr (==0.0.9)
33
34
  Requires-Dist: multidict (==6.0.5)
34
35
  Requires-Dist: open-aea-cli-ipfs (==1.65.0)
35
36
  Requires-Dist: open-aea-ledger-cosmos (==1.65.0)
@@ -38,6 +39,7 @@ Requires-Dist: open-aea-ledger-ethereum-flashbots (==1.65.0)
38
39
  Requires-Dist: open-autonomy (>=0.20.2,<0.21.0)
39
40
  Requires-Dist: psutil (>=5.9.8,<6.0.0)
40
41
  Requires-Dist: pyinstaller (>=6.8.0,<7.0.0)
42
+ Requires-Dist: requests-mock (>=1.12.1,<2.0.0)
41
43
  Requires-Dist: requests-toolbelt (==1.0.0)
42
44
  Requires-Dist: starlette (==0.37.2)
43
45
  Requires-Dist: twikit (==2.2.0)
@@ -42,10 +42,9 @@ from operate.bridge.providers.provider import Provider, ProviderRequest
42
42
  from operate.bridge.providers.relay_provider import RelayProvider
43
43
  from operate.constants import ZERO_ADDRESS
44
44
  from operate.ledger.profiles import USDC
45
- from operate.operate_types import Chain
45
+ from operate.operate_types import Chain, ChainAmounts
46
46
  from operate.resource import LocalResource
47
47
  from operate.services.manage import get_assets_balances
48
- from operate.utils import merge_sum_dicts, subtract_dicts
49
48
  from operate.wallet.master import MasterWalletManager
50
49
 
51
50
 
@@ -187,13 +186,13 @@ class BridgeManager:
187
186
  path: Path,
188
187
  wallet_manager: MasterWalletManager,
189
188
  logger: logging.Logger,
190
- quote_validity_period: int = DEFAULT_BUNDLE_VALIDITY_PERIOD,
189
+ bundle_validity_period: int = DEFAULT_BUNDLE_VALIDITY_PERIOD,
191
190
  ) -> None:
192
191
  """Initialize bridge manager."""
193
192
  self.path = path
194
193
  self.wallet_manager = wallet_manager
195
194
  self.logger = logger
196
- self.quote_validity_period = quote_validity_period
195
+ self.bundle_validity_period = bundle_validity_period
197
196
  self.path.mkdir(exist_ok=True)
198
197
  (self.path / EXECUTED_BUNDLES_PATH).mkdir(exist_ok=True)
199
198
  self.data: BridgeManagerData = cast(
@@ -251,7 +250,7 @@ class BridgeManager:
251
250
  self.logger.info("[BRIDGE MANAGER] Force bundle update.")
252
251
  self.quote_bundle(bundle)
253
252
  self._store_data()
254
- elif now > bundle.timestamp + self.quote_validity_period:
253
+ elif now > bundle.timestamp + self.bundle_validity_period:
255
254
  self.logger.info("[BRIDGE MANAGER] Bundle expired.")
256
255
  self.quote_bundle(bundle)
257
256
  self._store_data()
@@ -335,7 +334,7 @@ class BridgeManager:
335
334
 
336
335
  bundle = self._get_updated_bundle(requests_params, force_update)
337
336
 
338
- balances = {}
337
+ balances = ChainAmounts()
339
338
  for chain in bundle.get_from_chains():
340
339
  ledger_api = self.wallet_manager.load(chain.ledger_type).ledger_api(chain)
341
340
  balances[chain.value] = get_assets_balances(
@@ -346,9 +345,8 @@ class BridgeManager:
346
345
 
347
346
  bridge_total_requirements = self.bridge_total_requirements(bundle)
348
347
 
349
- bridge_refill_requirements = cast(
350
- t.Dict[str, t.Dict[str, t.Dict[str, int]]],
351
- subtract_dicts(bridge_total_requirements, balances),
348
+ bridge_refill_requirements = ChainAmounts.shortfalls(
349
+ bridge_total_requirements, balances
352
350
  )
353
351
 
354
352
  is_refill_required = any(
@@ -364,7 +362,7 @@ class BridgeManager:
364
362
  "balances": balances,
365
363
  "bridge_refill_requirements": bridge_refill_requirements,
366
364
  "bridge_total_requirements": bridge_total_requirements,
367
- "expiration_timestamp": bundle.timestamp + self.quote_validity_period,
365
+ "expiration_timestamp": bundle.timestamp + self.bundle_validity_period,
368
366
  "is_refill_required": is_refill_required,
369
367
  }
370
368
  )
@@ -441,14 +439,14 @@ class BridgeManager:
441
439
  "bridge_request_status": provider_request_status,
442
440
  }
443
441
 
444
- def bridge_total_requirements(self, bundle: ProviderRequestBundle) -> t.Dict:
442
+ def bridge_total_requirements(self, bundle: ProviderRequestBundle) -> ChainAmounts:
445
443
  """Sum bridge requirements."""
446
444
  requirements = []
447
445
  for provider_request in bundle.provider_requests:
448
446
  provider = self._providers[provider_request.provider_id]
449
447
  requirements.append(provider.requirements(provider_request))
450
448
 
451
- return merge_sum_dicts(*requirements)
449
+ return ChainAmounts.add(*requirements)
452
450
 
453
451
  def quote_bundle(self, bundle: ProviderRequestBundle) -> None:
454
452
  """Update the bundle with the quotes."""
@@ -38,6 +38,7 @@ from operate.bridge.providers.provider import (
38
38
  QuoteData,
39
39
  )
40
40
  from operate.constants import ZERO_ADDRESS
41
+ from operate.ledger import update_tx_with_gas_estimate, update_tx_with_gas_pricing
41
42
  from operate.operate_types import Chain
42
43
 
43
44
 
@@ -240,8 +241,8 @@ class LiFiProvider(Provider):
240
241
  amount=from_amount,
241
242
  )
242
243
  approve_tx["gas"] = 200_000 # TODO backport to ERC20 contract as default
243
- Provider._update_with_gas_pricing(approve_tx, from_ledger_api)
244
- Provider._update_with_gas_estimate(approve_tx, from_ledger_api)
244
+ update_tx_with_gas_pricing(approve_tx, from_ledger_api)
245
+ update_tx_with_gas_estimate(approve_tx, from_ledger_api)
245
246
  return approve_tx
246
247
 
247
248
  def _get_bridge_tx(self, provider_request: ProviderRequest) -> t.Optional[t.Dict]:
@@ -285,8 +286,8 @@ class LiFiProvider(Provider):
285
286
  transaction_request["from"]
286
287
  ),
287
288
  }
288
- Provider._update_with_gas_pricing(bridge_tx, from_ledger_api)
289
- Provider._update_with_gas_estimate(bridge_tx, from_ledger_api)
289
+ update_tx_with_gas_pricing(bridge_tx, from_ledger_api)
290
+ update_tx_with_gas_estimate(bridge_tx, from_ledger_api)
290
291
  return bridge_tx
291
292
 
292
293
  def _get_txs(
@@ -53,6 +53,7 @@ from operate.data.contracts.l2_standard_bridge.contract import L2StandardBridge
53
53
  from operate.data.contracts.optimism_mintable_erc20.contract import (
54
54
  OptimismMintableERC20,
55
55
  )
56
+ from operate.ledger import update_tx_with_gas_estimate, update_tx_with_gas_pricing
56
57
  from operate.ledger.profiles import ERC20_TOKENS, EXPLORER_URL
57
58
  from operate.operate_types import Chain
58
59
  from operate.wallet.master import MasterWalletManager
@@ -96,7 +97,7 @@ class BridgeContractAdaptor(ABC):
96
97
  if from_token == ZERO_ADDRESS and to_token == ZERO_ADDRESS:
97
98
  return True
98
99
 
99
- for token_map in ERC20_TOKENS:
100
+ for token_map in ERC20_TOKENS.values():
100
101
  if (
101
102
  Chain(from_chain) in token_map
102
103
  and Chain(to_chain) in token_map
@@ -512,8 +513,8 @@ class NativeBridgeProvider(Provider):
512
513
  amount=to_amount,
513
514
  )
514
515
  approve_tx["gas"] = 200_000 # TODO backport to ERC20 contract as default
515
- Provider._update_with_gas_pricing(approve_tx, from_ledger_api)
516
- Provider._update_with_gas_estimate(approve_tx, from_ledger_api)
516
+ update_tx_with_gas_pricing(approve_tx, from_ledger_api)
517
+ update_tx_with_gas_estimate(approve_tx, from_ledger_api)
517
518
  return approve_tx
518
519
 
519
520
  def _get_bridge_tx(self, provider_request: ProviderRequest) -> t.Optional[t.Dict]:
@@ -534,8 +535,8 @@ class NativeBridgeProvider(Provider):
534
535
  from_ledger_api=from_ledger_api, provider_request=provider_request
535
536
  )
536
537
 
537
- Provider._update_with_gas_pricing(bridge_tx, from_ledger_api)
538
- Provider._update_with_gas_estimate(bridge_tx, from_ledger_api)
538
+ update_tx_with_gas_pricing(bridge_tx, from_ledger_api)
539
+ update_tx_with_gas_estimate(bridge_tx, from_ledger_api)
539
540
  return bridge_tx
540
541
 
541
542
  def _get_txs(
@@ -28,12 +28,10 @@ import typing as t
28
28
  import uuid
29
29
  from abc import ABC, abstractmethod
30
30
  from dataclasses import dataclass
31
- from math import ceil
32
31
 
33
32
  from aea.crypto.base import LedgerApi
34
33
  from autonomy.chain.tx import TxSettler
35
34
  from web3 import Web3
36
- from web3.middleware import geth_poa_middleware
37
35
 
38
36
  from operate.constants import (
39
37
  ON_CHAIN_INTERACT_RETRIES,
@@ -41,16 +39,12 @@ from operate.constants import (
41
39
  ON_CHAIN_INTERACT_TIMEOUT,
42
40
  ZERO_ADDRESS,
43
41
  )
44
- from operate.operate_types import Chain
42
+ from operate.ledger import get_default_ledger_api, update_tx_with_gas_pricing
43
+ from operate.operate_types import Chain, ChainAmounts
45
44
  from operate.resource import LocalResource
46
45
  from operate.wallet.master import MasterWalletManager
47
46
 
48
47
 
49
- GAS_ESTIMATE_FALLBACK_ADDRESSES = [
50
- "0x000000000000000000000000000000000000dEaD",
51
- "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", # nosec
52
- ]
53
-
54
48
  DEFAULT_MAX_QUOTE_RETRIES = 3
55
49
  PROVIDER_REQUEST_PREFIX = "r-"
56
50
  MESSAGE_QUOTE_ZERO = "Zero-amount quote requested."
@@ -66,8 +60,6 @@ MESSAGE_REQUIREMENTS_QUOTE_FAILED = "Cannot compute requirements for failed quot
66
60
 
67
61
  ERC20_APPROVE_SELECTOR = "0x095ea7b3" # First 4 bytes of Web3.keccak(text='approve(address,uint256)').hex()[:10]
68
62
 
69
- GAS_ESTIMATE_BUFFER = 1.10
70
-
71
63
 
72
64
  @dataclass
73
65
  class QuoteData(LocalResource):
@@ -225,28 +217,12 @@ class Provider(ABC):
225
217
  def _from_ledger_api(self, provider_request: ProviderRequest) -> LedgerApi:
226
218
  """Get the from ledger api."""
227
219
  from_chain = provider_request.params["from"]["chain"]
228
- chain = Chain(from_chain)
229
- wallet = self.wallet_manager.load(chain.ledger_type)
230
- ledger_api = wallet.ledger_api(chain)
231
-
232
- # TODO: Backport to open aea/autonomy
233
- if chain == Chain.OPTIMISM:
234
- ledger_api.api.middleware_onion.inject(geth_poa_middleware, layer=0)
235
-
236
- return ledger_api
220
+ return get_default_ledger_api(Chain(from_chain))
237
221
 
238
222
  def _to_ledger_api(self, provider_request: ProviderRequest) -> LedgerApi:
239
223
  """Get the from ledger api."""
240
- from_chain = provider_request.params["to"]["chain"]
241
- chain = Chain(from_chain)
242
- wallet = self.wallet_manager.load(chain.ledger_type)
243
- ledger_api = wallet.ledger_api(chain)
244
-
245
- # TODO: Backport to open aea/autonomy
246
- if chain == Chain.OPTIMISM:
247
- ledger_api.api.middleware_onion.inject(geth_poa_middleware, layer=0)
248
-
249
- return ledger_api
224
+ to_chain = provider_request.params["to"]["chain"]
225
+ return get_default_ledger_api(Chain(to_chain))
250
226
 
251
227
  @abstractmethod
252
228
  def quote(self, provider_request: ProviderRequest) -> None:
@@ -260,7 +236,7 @@ class Provider(ABC):
260
236
  """Get the sorted list of transactions to execute the quote."""
261
237
  raise NotImplementedError()
262
238
 
263
- def requirements(self, provider_request: ProviderRequest) -> t.Dict:
239
+ def requirements(self, provider_request: ProviderRequest) -> ChainAmounts:
264
240
  """Gets the requirements to execute the quote, with updated gas estimation."""
265
241
  self.logger.info(f"[PROVIDER] Requirements for request {provider_request.id}.")
266
242
 
@@ -274,14 +250,16 @@ class Provider(ABC):
274
250
  txs = self._get_txs(provider_request)
275
251
 
276
252
  if not txs:
277
- return {
278
- from_chain: {
279
- from_address: {
280
- ZERO_ADDRESS: 0,
281
- from_token: 0,
253
+ return ChainAmounts(
254
+ {
255
+ from_chain: {
256
+ from_address: {
257
+ ZERO_ADDRESS: 0,
258
+ from_token: 0,
259
+ }
282
260
  }
283
261
  }
284
- }
262
+ )
285
263
 
286
264
  total_native = 0
287
265
  total_gas_fees = 0
@@ -291,7 +269,7 @@ class Provider(ABC):
291
269
  self.logger.debug(
292
270
  f"[PROVIDER] Processing transaction {tx_label} for request {provider_request.id}."
293
271
  )
294
- self._update_with_gas_pricing(tx, from_ledger_api)
272
+ update_tx_with_gas_pricing(tx, from_ledger_api)
295
273
  gas_key = "gasPrice" if "gasPrice" in tx else "maxFeePerGas"
296
274
  gas_fees = tx.get(gas_key, 0) * tx["gas"]
297
275
  tx_value = int(tx.get("value", 0))
@@ -319,13 +297,15 @@ class Provider(ABC):
319
297
  f"[PROVIDER] Total gas fees for request {provider_request.id}: {total_gas_fees} native units."
320
298
  )
321
299
 
322
- result = {
323
- from_chain: {
324
- from_address: {
325
- ZERO_ADDRESS: total_native,
300
+ result = ChainAmounts(
301
+ {
302
+ from_chain: {
303
+ from_address: {
304
+ ZERO_ADDRESS: total_native,
305
+ }
326
306
  }
327
307
  }
328
- }
308
+ )
329
309
 
330
310
  if from_token != ZERO_ADDRESS:
331
311
  result[from_chain][from_address][from_token] = total_token
@@ -487,48 +467,3 @@ class Provider(ABC):
487
467
  receipt = ledger_api.api.eth.get_transaction_receipt(tx_hash)
488
468
  block = ledger_api.api.eth.get_block(receipt.blockNumber)
489
469
  return block.timestamp
490
-
491
- # TODO backport to open aea/autonomy
492
- # TODO This gas pricing management should possibly be done at a lower level in the library
493
- @staticmethod
494
- def _update_with_gas_pricing(tx: t.Dict, ledger_api: LedgerApi) -> None:
495
- tx.pop("maxFeePerGas", None)
496
- tx.pop("gasPrice", None)
497
- tx.pop("maxPriorityFeePerGas", None)
498
-
499
- gas_pricing = ledger_api.try_get_gas_pricing()
500
- if gas_pricing is None:
501
- raise RuntimeError("Unable to retrieve gas pricing.")
502
-
503
- if "maxFeePerGas" in gas_pricing and "maxPriorityFeePerGas" in gas_pricing:
504
- tx["maxFeePerGas"] = gas_pricing["maxFeePerGas"]
505
- tx["maxPriorityFeePerGas"] = gas_pricing["maxPriorityFeePerGas"]
506
- elif "gasPrice" in gas_pricing:
507
- tx["gasPrice"] = gas_pricing["gasPrice"]
508
- else:
509
- raise RuntimeError("Retrieved invalid gas pricing.")
510
-
511
- # TODO backport to open aea/autonomy
512
- @staticmethod
513
- def _update_with_gas_estimate(tx: t.Dict, ledger_api: LedgerApi) -> None:
514
- print(
515
- f"[PROVIDER] Trying to update transaction gas {tx['from']=} {tx['gas']=}."
516
- )
517
- original_from = tx["from"]
518
- original_gas = tx.get("gas", 1)
519
-
520
- for address in [original_from] + GAS_ESTIMATE_FALLBACK_ADDRESSES:
521
- tx["from"] = address
522
- tx["gas"] = 1
523
- ledger_api.update_with_gas_estimate(tx)
524
- if tx["gas"] > 1:
525
- print(
526
- f"[PROVIDER] Gas estimated successfully {tx['from']=} {tx['gas']=}."
527
- )
528
- break
529
-
530
- tx["from"] = original_from
531
- if tx["gas"] == 1:
532
- tx["gas"] = original_gas
533
- print(f"[PROVIDER] Unable to estimate gas. Restored {tx['gas']=}.")
534
- tx["gas"] = ceil(tx["gas"] * GAS_ESTIMATE_BUFFER)
@@ -39,6 +39,7 @@ from operate.bridge.providers.provider import (
39
39
  ProviderRequestStatus,
40
40
  QuoteData,
41
41
  )
42
+ from operate.ledger import update_tx_with_gas_estimate, update_tx_with_gas_pricing
42
43
  from operate.operate_types import Chain
43
44
 
44
45
 
@@ -258,10 +259,10 @@ class RelayProvider(Provider):
258
259
  timestamp=int(time.time()),
259
260
  )
260
261
  except requests.RequestException as e:
262
+ response_json = response.json()
261
263
  self.logger.warning(
262
- f"[RELAY PROVIDER] Request failed on attempt {attempt}/{DEFAULT_MAX_QUOTE_RETRIES}: {e}."
264
+ f"[RELAY PROVIDER] Request failed on attempt {attempt}/{DEFAULT_MAX_QUOTE_RETRIES}: {response_json}."
263
265
  )
264
- response_json = response.json()
265
266
  quote_data = QuoteData(
266
267
  eta=None,
267
268
  elapsed_time=time.time() - start,
@@ -338,8 +339,8 @@ class RelayProvider(Provider):
338
339
  tx["maxFeePerGas"] = int(tx.get("maxFeePerGas", 0))
339
340
  tx["maxPriorityFeePerGas"] = int(tx.get("maxPriorityFeePerGas", 0))
340
341
  tx["nonce"] = from_ledger_api.api.eth.get_transaction_count(tx["from"])
341
- Provider._update_with_gas_pricing(tx, from_ledger_api)
342
- Provider._update_with_gas_estimate(tx, from_ledger_api)
342
+ update_tx_with_gas_pricing(tx, from_ledger_api)
343
+ update_tx_with_gas_estimate(tx, from_ledger_api)
343
344
  txs.append((f"{step['id']}-{i}", tx))
344
345
 
345
346
  return txs