olas-operate-middleware 0.1.0rc59__py3-none-any.whl → 0.13.2__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.
- olas_operate_middleware-0.13.2.dist-info/METADATA +75 -0
- olas_operate_middleware-0.13.2.dist-info/RECORD +101 -0
- {olas_operate_middleware-0.1.0rc59.dist-info → olas_operate_middleware-0.13.2.dist-info}/WHEEL +1 -1
- operate/__init__.py +17 -0
- operate/account/user.py +35 -9
- operate/bridge/bridge_manager.py +470 -0
- operate/bridge/providers/lifi_provider.py +377 -0
- operate/bridge/providers/native_bridge_provider.py +677 -0
- operate/bridge/providers/provider.py +469 -0
- operate/bridge/providers/relay_provider.py +457 -0
- operate/cli.py +1565 -417
- operate/constants.py +60 -12
- operate/data/README.md +19 -0
- operate/data/contracts/{service_staking_token → dual_staking_token}/__init__.py +2 -2
- operate/data/contracts/dual_staking_token/build/DualStakingToken.json +443 -0
- operate/data/contracts/dual_staking_token/contract.py +132 -0
- operate/data/contracts/dual_staking_token/contract.yaml +23 -0
- operate/{ledger/base.py → data/contracts/foreign_omnibridge/__init__.py} +2 -19
- operate/data/contracts/foreign_omnibridge/build/ForeignOmnibridge.json +1372 -0
- operate/data/contracts/foreign_omnibridge/contract.py +130 -0
- operate/data/contracts/foreign_omnibridge/contract.yaml +23 -0
- operate/{ledger/solana.py → data/contracts/home_omnibridge/__init__.py} +2 -20
- operate/data/contracts/home_omnibridge/build/HomeOmnibridge.json +1421 -0
- operate/data/contracts/home_omnibridge/contract.py +80 -0
- operate/data/contracts/home_omnibridge/contract.yaml +23 -0
- operate/data/contracts/l1_standard_bridge/__init__.py +20 -0
- operate/data/contracts/l1_standard_bridge/build/L1StandardBridge.json +831 -0
- operate/data/contracts/l1_standard_bridge/contract.py +158 -0
- operate/data/contracts/l1_standard_bridge/contract.yaml +23 -0
- operate/data/contracts/l2_standard_bridge/__init__.py +20 -0
- operate/data/contracts/l2_standard_bridge/build/L2StandardBridge.json +626 -0
- operate/data/contracts/l2_standard_bridge/contract.py +130 -0
- operate/data/contracts/l2_standard_bridge/contract.yaml +23 -0
- operate/data/contracts/mech_activity/__init__.py +20 -0
- operate/data/contracts/mech_activity/build/MechActivity.json +111 -0
- operate/data/contracts/mech_activity/contract.py +44 -0
- operate/data/contracts/mech_activity/contract.yaml +23 -0
- operate/data/contracts/optimism_mintable_erc20/__init__.py +20 -0
- operate/data/contracts/optimism_mintable_erc20/build/OptimismMintableERC20.json +491 -0
- operate/data/contracts/optimism_mintable_erc20/contract.py +45 -0
- operate/data/contracts/optimism_mintable_erc20/contract.yaml +23 -0
- operate/data/contracts/recovery_module/__init__.py +20 -0
- operate/data/contracts/recovery_module/build/RecoveryModule.json +811 -0
- operate/data/contracts/recovery_module/contract.py +61 -0
- operate/data/contracts/recovery_module/contract.yaml +23 -0
- operate/data/contracts/requester_activity_checker/__init__.py +20 -0
- operate/data/contracts/requester_activity_checker/build/RequesterActivityChecker.json +111 -0
- operate/data/contracts/requester_activity_checker/contract.py +33 -0
- operate/data/contracts/requester_activity_checker/contract.yaml +23 -0
- operate/data/contracts/staking_token/__init__.py +20 -0
- operate/data/contracts/staking_token/build/StakingToken.json +1336 -0
- operate/data/contracts/{service_staking_token → staking_token}/contract.py +27 -13
- operate/data/contracts/staking_token/contract.yaml +23 -0
- operate/data/contracts/uniswap_v2_erc20/contract.yaml +3 -1
- operate/data/contracts/uniswap_v2_erc20/tests/__init__.py +20 -0
- operate/data/contracts/uniswap_v2_erc20/tests/test_contract.py +363 -0
- operate/keys.py +118 -33
- operate/ledger/__init__.py +159 -56
- operate/ledger/profiles.py +321 -18
- operate/migration.py +555 -0
- operate/{http → operate_http}/__init__.py +3 -2
- operate/{http → operate_http}/exceptions.py +6 -4
- operate/operate_types.py +544 -0
- operate/pearl.py +13 -1
- operate/quickstart/analyse_logs.py +118 -0
- operate/quickstart/claim_staking_rewards.py +104 -0
- operate/quickstart/reset_configs.py +106 -0
- operate/quickstart/reset_password.py +70 -0
- operate/quickstart/reset_staking.py +145 -0
- operate/quickstart/run_service.py +726 -0
- operate/quickstart/stop_service.py +72 -0
- operate/quickstart/terminate_on_chain_service.py +83 -0
- operate/quickstart/utils.py +298 -0
- operate/resource.py +62 -3
- operate/services/agent_runner.py +202 -0
- operate/services/deployment_runner.py +868 -0
- operate/services/funding_manager.py +929 -0
- operate/services/health_checker.py +280 -0
- operate/services/manage.py +2356 -620
- operate/services/protocol.py +1246 -340
- operate/services/service.py +756 -391
- operate/services/utils/mech.py +103 -0
- operate/services/utils/tendermint.py +86 -12
- operate/settings.py +70 -0
- operate/utils/__init__.py +135 -0
- operate/utils/gnosis.py +407 -80
- operate/utils/single_instance.py +226 -0
- operate/utils/ssl.py +133 -0
- operate/wallet/master.py +708 -123
- operate/wallet/wallet_recovery_manager.py +507 -0
- olas_operate_middleware-0.1.0rc59.dist-info/METADATA +0 -304
- olas_operate_middleware-0.1.0rc59.dist-info/RECORD +0 -41
- operate/data/contracts/service_staking_token/build/ServiceStakingToken.json +0 -1273
- operate/data/contracts/service_staking_token/contract.yaml +0 -23
- operate/ledger/ethereum.py +0 -48
- operate/types.py +0 -260
- {olas_operate_middleware-0.1.0rc59.dist-info → olas_operate_middleware-0.13.2.dist-info}/entry_points.txt +0 -0
- {olas_operate_middleware-0.1.0rc59.dist-info → olas_operate_middleware-0.13.2.dist-info/licenses}/LICENSE +0 -0
operate/ledger/__init__.py
CHANGED
|
@@ -21,79 +21,182 @@
|
|
|
21
21
|
|
|
22
22
|
import os
|
|
23
23
|
import typing as t
|
|
24
|
+
from copy import deepcopy
|
|
25
|
+
from math import ceil
|
|
26
|
+
|
|
27
|
+
from aea.crypto.base import LedgerApi
|
|
28
|
+
from aea.crypto.registries import make_ledger_api
|
|
29
|
+
from aea_ledger_ethereum import DEFAULT_GAS_PRICE_STRATEGIES, EIP1559, GWEI, to_wei
|
|
30
|
+
from web3.middleware import geth_poa_middleware
|
|
31
|
+
|
|
32
|
+
from operate.operate_types import Chain
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
CHAINS = [
|
|
36
|
+
Chain.ARBITRUM_ONE,
|
|
37
|
+
Chain.BASE,
|
|
38
|
+
Chain.CELO,
|
|
39
|
+
Chain.ETHEREUM,
|
|
40
|
+
Chain.GNOSIS,
|
|
41
|
+
Chain.MODE,
|
|
42
|
+
Chain.OPTIMISM,
|
|
43
|
+
Chain.POLYGON,
|
|
44
|
+
Chain.SOLANA,
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
ARBITRUM_ONE_RPC = os.environ.get("ARBITRUM_ONE_RPC", "https://arb1.arbitrum.io/rpc")
|
|
48
|
+
BASE_RPC = os.environ.get("BASE_RPC", "https://mainnet.base.org")
|
|
49
|
+
CELO_RPC = os.environ.get("CELO_RPC", "https://forno.celo.org")
|
|
50
|
+
ETHEREUM_RPC = os.environ.get("ETHEREUM_RPC", "https://ethereum.publicnode.com")
|
|
51
|
+
GNOSIS_RPC = os.environ.get("GNOSIS_RPC", "https://gnosis-rpc.publicnode.com")
|
|
52
|
+
MODE_RPC = os.environ.get("MODE_RPC", "https://mainnet.mode.network")
|
|
53
|
+
OPTIMISM_RPC = os.environ.get("OPTIMISM_RPC", "https://mainnet.optimism.io")
|
|
54
|
+
POLYGON_RPC = os.environ.get("POLYGON_RPC", "https://polygon-rpc.com")
|
|
55
|
+
SOLANA_RPC = os.environ.get("SOLANA_RPC", "https://api.mainnet-beta.solana.com")
|
|
24
56
|
|
|
25
|
-
from operate.ledger.base import LedgerHelper
|
|
26
|
-
from operate.ledger.ethereum import Ethereum
|
|
27
|
-
from operate.ledger.solana import Solana
|
|
28
|
-
from operate.types import ChainType, LedgerType
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
ETHEREUM_PUBLIC_RPC = os.environ.get("DEV_RPC", "https://ethereum.publicnode.com")
|
|
32
|
-
GNOSIS_PUBLIC_RPC = os.environ.get("DEV_RPC", "https://gnosis-rpc.publicnode.com")
|
|
33
|
-
GOERLI_PUBLIC_RPC = os.environ.get("DEV_RPC", "https://ethereum-goerli.publicnode.com")
|
|
34
|
-
SOLANA_PUBLIC_RPC = os.environ.get("DEV_RPC", "https://api.mainnet-beta.solana.com")
|
|
35
|
-
|
|
36
|
-
ETHEREUM_RPC = os.environ.get("DEV_RPC", "https://ethereum.publicnode.com")
|
|
37
|
-
GNOSIS_RPC = os.environ.get("DEV_RPC", "https://rpc-gate.autonolas.tech/gnosis-rpc/")
|
|
38
|
-
GOERLI_RPC = os.environ.get("DEV_RPC", "https://ethereum-goerli.publicnode.com")
|
|
39
|
-
SOLANA_RPC = os.environ.get("DEV_RPC", "https://api.mainnet-beta.solana.com")
|
|
40
|
-
|
|
41
|
-
PUBLIC_RPCS = {
|
|
42
|
-
ChainType.ETHEREUM: ETHEREUM_PUBLIC_RPC,
|
|
43
|
-
ChainType.GNOSIS: GNOSIS_PUBLIC_RPC,
|
|
44
|
-
ChainType.GOERLI: GOERLI_PUBLIC_RPC,
|
|
45
|
-
ChainType.SOLANA: SOLANA_PUBLIC_RPC,
|
|
46
|
-
}
|
|
47
57
|
|
|
48
58
|
DEFAULT_RPCS = {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
Chain.ARBITRUM_ONE: ARBITRUM_ONE_RPC,
|
|
60
|
+
Chain.BASE: BASE_RPC,
|
|
61
|
+
Chain.CELO: CELO_RPC,
|
|
62
|
+
Chain.ETHEREUM: ETHEREUM_RPC,
|
|
63
|
+
Chain.GNOSIS: GNOSIS_RPC,
|
|
64
|
+
Chain.MODE: MODE_RPC,
|
|
65
|
+
Chain.OPTIMISM: OPTIMISM_RPC,
|
|
66
|
+
Chain.POLYGON: POLYGON_RPC,
|
|
67
|
+
Chain.SOLANA: SOLANA_RPC,
|
|
53
68
|
}
|
|
54
69
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
70
|
+
# Base currency for each chain
|
|
71
|
+
CURRENCY_DENOMS = {
|
|
72
|
+
Chain.ARBITRUM_ONE: "ETH",
|
|
73
|
+
Chain.BASE: "ETH",
|
|
74
|
+
Chain.CELO: "CELO",
|
|
75
|
+
Chain.ETHEREUM: "ETH",
|
|
76
|
+
Chain.GNOSIS: "xDAI",
|
|
77
|
+
Chain.MODE: "ETH",
|
|
78
|
+
Chain.OPTIMISM: "ETH",
|
|
79
|
+
Chain.POLYGON: "POL",
|
|
80
|
+
Chain.SOLANA: "SOL",
|
|
60
81
|
}
|
|
61
82
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
83
|
+
# Smallest denomination for each chain
|
|
84
|
+
CURRENCY_SMALLEST_UNITS = {
|
|
85
|
+
Chain.ARBITRUM_ONE: "Wei",
|
|
86
|
+
Chain.BASE: "Wei",
|
|
87
|
+
Chain.CELO: "Wei",
|
|
88
|
+
Chain.ETHEREUM: "Wei",
|
|
89
|
+
Chain.GNOSIS: "Wei",
|
|
90
|
+
Chain.MODE: "Wei",
|
|
91
|
+
Chain.OPTIMISM: "Wei",
|
|
92
|
+
Chain.POLYGON: "Wei",
|
|
93
|
+
Chain.SOLANA: "Lamport",
|
|
65
94
|
}
|
|
66
95
|
|
|
67
|
-
|
|
68
|
-
ChainType.ETHEREUM: "Wei",
|
|
69
|
-
ChainType.GNOSIS: "xDai",
|
|
70
|
-
ChainType.GOERLI: "GWei",
|
|
71
|
-
ChainType.SOLANA: "Lamp",
|
|
72
|
-
}
|
|
96
|
+
NATIVE_CURRENCY_DECIMALS = 18
|
|
73
97
|
|
|
74
98
|
|
|
75
|
-
def get_default_rpc(chain:
|
|
99
|
+
def get_default_rpc(chain: Chain) -> str:
|
|
76
100
|
"""Get default RPC chain type."""
|
|
77
|
-
return DEFAULT_RPCS
|
|
101
|
+
return DEFAULT_RPCS[chain]
|
|
78
102
|
|
|
79
103
|
|
|
80
|
-
def
|
|
81
|
-
"""Get
|
|
82
|
-
|
|
83
|
-
return LedgerType.ETHEREUM
|
|
84
|
-
return LedgerType.SOLANA
|
|
104
|
+
def get_currency_denom(chain: Chain) -> str:
|
|
105
|
+
"""Get currency denom by chain type."""
|
|
106
|
+
return CURRENCY_DENOMS.get(chain, "NATIVE")
|
|
85
107
|
|
|
86
108
|
|
|
87
|
-
def
|
|
88
|
-
"""Get
|
|
89
|
-
return
|
|
109
|
+
def get_currency_smallest_unit(chain: Chain) -> str:
|
|
110
|
+
"""Get currency denom by chain type."""
|
|
111
|
+
return CURRENCY_SMALLEST_UNITS.get(chain, "Wei")
|
|
90
112
|
|
|
91
113
|
|
|
92
|
-
|
|
93
|
-
"""Get ledger helper by ledger type."""
|
|
94
|
-
return LEDGER_HELPERS.get(ledger, Ethereum)(rpc=rpc) # type: ignore
|
|
114
|
+
DEFAULT_LEDGER_APIS: t.Dict[Chain, LedgerApi] = {}
|
|
95
115
|
|
|
96
116
|
|
|
97
|
-
def
|
|
98
|
-
|
|
99
|
-
|
|
117
|
+
def make_chain_ledger_api(
|
|
118
|
+
chain: Chain,
|
|
119
|
+
rpc: t.Optional[str] = None,
|
|
120
|
+
) -> LedgerApi:
|
|
121
|
+
"""Get default RPC chain type."""
|
|
122
|
+
if chain == Chain.SOLANA: # TODO: Complete when Solana is supported
|
|
123
|
+
raise NotImplementedError("Solana not yet supported.")
|
|
124
|
+
|
|
125
|
+
gas_price_strategies = deepcopy(DEFAULT_GAS_PRICE_STRATEGIES)
|
|
126
|
+
if chain in (Chain.BASE, Chain.MODE, Chain.OPTIMISM):
|
|
127
|
+
gas_price_strategies[EIP1559]["fallback_estimate"]["maxFeePerGas"] = to_wei(
|
|
128
|
+
5, GWEI
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
ledger_api = make_ledger_api(
|
|
132
|
+
chain.ledger_type.name.lower(),
|
|
133
|
+
address=rpc or get_default_rpc(chain=chain),
|
|
134
|
+
chain_id=chain.id,
|
|
135
|
+
gas_price_strategies=gas_price_strategies,
|
|
136
|
+
poa_chain=chain == Chain.POLYGON,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
if chain == Chain.OPTIMISM:
|
|
140
|
+
ledger_api.api.middleware_onion.inject(geth_poa_middleware, layer=0)
|
|
141
|
+
|
|
142
|
+
return ledger_api
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def get_default_ledger_api(chain: Chain) -> LedgerApi:
|
|
146
|
+
"""Get default RPC chain type."""
|
|
147
|
+
if chain not in DEFAULT_LEDGER_APIS:
|
|
148
|
+
DEFAULT_LEDGER_APIS[chain] = make_chain_ledger_api(
|
|
149
|
+
chain=chain, rpc=get_default_rpc(chain=chain)
|
|
150
|
+
)
|
|
151
|
+
return DEFAULT_LEDGER_APIS[chain]
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
GAS_ESTIMATE_FALLBACK_ADDRESSES = [
|
|
155
|
+
"0x000000000000000000000000000000000000dEaD",
|
|
156
|
+
"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", # nosec
|
|
157
|
+
]
|
|
158
|
+
GAS_ESTIMATE_BUFFER = 1.10
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
# TODO backport to open aea/autonomy
|
|
162
|
+
# TODO This gas pricing management should be done at a lower level in the library
|
|
163
|
+
def update_tx_with_gas_pricing(tx: t.Dict, ledger_api: LedgerApi) -> None:
|
|
164
|
+
"""Update transaction with gas pricing."""
|
|
165
|
+
tx.pop("maxFeePerGas", None)
|
|
166
|
+
tx.pop("gasPrice", None)
|
|
167
|
+
tx.pop("maxPriorityFeePerGas", None)
|
|
168
|
+
|
|
169
|
+
gas_pricing = ledger_api.try_get_gas_pricing()
|
|
170
|
+
if gas_pricing is None:
|
|
171
|
+
raise RuntimeError("Unable to retrieve gas pricing.")
|
|
172
|
+
|
|
173
|
+
if "maxFeePerGas" in gas_pricing and "maxPriorityFeePerGas" in gas_pricing:
|
|
174
|
+
tx["maxFeePerGas"] = gas_pricing["maxFeePerGas"]
|
|
175
|
+
tx["maxPriorityFeePerGas"] = gas_pricing["maxPriorityFeePerGas"]
|
|
176
|
+
elif "gasPrice" in gas_pricing:
|
|
177
|
+
tx["gasPrice"] = gas_pricing["gasPrice"]
|
|
178
|
+
else:
|
|
179
|
+
raise RuntimeError("Retrieved invalid gas pricing.")
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
# TODO backport to open aea/autonomy
|
|
183
|
+
# TODO This gas management should be done at a lower level in the library
|
|
184
|
+
def update_tx_with_gas_estimate(tx: t.Dict, ledger_api: LedgerApi) -> None:
|
|
185
|
+
"""Update transaction with gas estimate."""
|
|
186
|
+
print(f"[LEDGER] Trying to update transaction gas {tx['from']=} {tx['gas']=}.")
|
|
187
|
+
original_from = tx["from"]
|
|
188
|
+
original_gas = tx.get("gas", 1)
|
|
189
|
+
|
|
190
|
+
for address in [original_from] + GAS_ESTIMATE_FALLBACK_ADDRESSES:
|
|
191
|
+
tx["from"] = address
|
|
192
|
+
tx["gas"] = 1
|
|
193
|
+
ledger_api.update_with_gas_estimate(tx)
|
|
194
|
+
if tx["gas"] > 1:
|
|
195
|
+
print(f"[LEDGER] Gas estimated successfully {tx['from']=} {tx['gas']=}.")
|
|
196
|
+
break
|
|
197
|
+
|
|
198
|
+
tx["from"] = original_from
|
|
199
|
+
if tx["gas"] == 1:
|
|
200
|
+
tx["gas"] = original_gas
|
|
201
|
+
print(f"[LEDGER] Unable to estimate gas. Restored {tx['gas']=}.")
|
|
202
|
+
tx["gas"] = ceil(tx["gas"] * GAS_ESTIMATE_BUFFER)
|
operate/ledger/profiles.py
CHANGED
|
@@ -19,26 +19,329 @@
|
|
|
19
19
|
|
|
20
20
|
"""Chain profiles."""
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
import typing as t
|
|
23
|
+
from functools import cache
|
|
24
|
+
|
|
25
|
+
from autonomy.chain.base import registry_contracts
|
|
26
|
+
from autonomy.chain.constants import CHAIN_PROFILES, DEFAULT_MULTISEND
|
|
27
|
+
|
|
28
|
+
from operate.constants import NO_STAKING_PROGRAM_ID, ZERO_ADDRESS
|
|
29
|
+
from operate.ledger import (
|
|
30
|
+
CHAINS,
|
|
31
|
+
NATIVE_CURRENCY_DECIMALS,
|
|
32
|
+
get_currency_denom,
|
|
33
|
+
get_default_ledger_api,
|
|
34
|
+
)
|
|
35
|
+
from operate.operate_types import Chain, ContractAddresses
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# TODO: Refactor, remove the usage of CONTRACTS and use CHAIN_PROFILES from Open Autonomy instead.
|
|
39
|
+
CONTRACTS: t.Dict[Chain, ContractAddresses] = {}
|
|
40
|
+
for _chain in CHAINS:
|
|
41
|
+
if _chain.value in CHAIN_PROFILES:
|
|
42
|
+
profile = CHAIN_PROFILES[_chain.value]
|
|
43
|
+
CONTRACTS[_chain] = ContractAddresses(
|
|
44
|
+
{
|
|
45
|
+
"service_registry": profile["service_registry"],
|
|
46
|
+
"service_registry_token_utility": profile[
|
|
47
|
+
"service_registry_token_utility"
|
|
48
|
+
],
|
|
49
|
+
"service_manager": profile["service_manager_token"],
|
|
50
|
+
"gnosis_safe_proxy_factory": profile["gnosis_safe_proxy_factory"],
|
|
51
|
+
"gnosis_safe_same_address_multisig": profile[
|
|
52
|
+
"gnosis_safe_same_address_multisig"
|
|
53
|
+
],
|
|
54
|
+
"safe_multisig_with_recovery_module": profile[
|
|
55
|
+
"safe_multisig_with_recovery_module"
|
|
56
|
+
],
|
|
57
|
+
"recovery_module": profile["recovery_module"],
|
|
58
|
+
"multisend": DEFAULT_MULTISEND,
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
STAKING: t.Dict[Chain, t.Dict[str, str]] = {
|
|
63
|
+
Chain.ARBITRUM_ONE: {},
|
|
64
|
+
Chain.GNOSIS: {
|
|
65
|
+
"pearl_alpha": "0xEE9F19b5DF06c7E8Bfc7B28745dcf944C504198A",
|
|
66
|
+
"pearl_beta": "0xeF44Fb0842DDeF59D37f85D61A1eF492bbA6135d",
|
|
67
|
+
"pearl_beta_2": "0x1c2F82413666d2a3fD8bC337b0268e62dDF67434",
|
|
68
|
+
"pearl_beta_3": "0xBd59Ff0522aA773cB6074ce83cD1e4a05A457bc1",
|
|
69
|
+
"pearl_beta_4": "0x3052451e1eAee78e62E169AfdF6288F8791F2918",
|
|
70
|
+
"pearl_beta_5": "0x4Abe376Fda28c2F43b84884E5f822eA775DeA9F4",
|
|
71
|
+
"pearl_beta_6": "0x6C6D01e8eA8f806eF0c22F0ef7ed81D868C1aB39",
|
|
72
|
+
"pearl_beta_mech_marketplace": "0xDaF34eC46298b53a3d24CBCb431E84eBd23927dA",
|
|
73
|
+
"quickstart_beta_hobbyist": "0x389B46c259631Acd6a69Bde8B6cEe218230bAE8C",
|
|
74
|
+
"quickstart_beta_hobbyist_2": "0x238EB6993b90a978ec6AAD7530d6429c949C08DA",
|
|
75
|
+
"quickstart_beta_expert": "0x5344B7DD311e5d3DdDd46A4f71481bD7b05AAA3e",
|
|
76
|
+
"quickstart_beta_expert_2": "0xb964e44c126410df341ae04B13aB10A985fE3513",
|
|
77
|
+
"quickstart_beta_expert_3": "0x80faD33Cadb5F53f9D29F02Db97D682E8b101618",
|
|
78
|
+
"quickstart_beta_expert_4": "0xaD9d891134443B443D7F30013c7e14Fe27F2E029",
|
|
79
|
+
"quickstart_beta_expert_5": "0xE56dF1E563De1B10715cB313D514af350D207212",
|
|
80
|
+
"quickstart_beta_expert_6": "0x2546214aEE7eEa4bEE7689C81231017CA231Dc93",
|
|
81
|
+
"quickstart_beta_expert_7": "0xD7A3C8b975f71030135f1a66e9e23164d54fF455",
|
|
82
|
+
"quickstart_beta_expert_8": "0x356C108D49C5eebd21c84c04E9162de41933030c",
|
|
83
|
+
"quickstart_beta_expert_9": "0x17dBAe44BC5618Cc254055b386A29576b4F87015",
|
|
84
|
+
"quickstart_beta_expert_10": "0xB0ef657b8302bd2c74B6E6D9B2b4b39145b19c6f",
|
|
85
|
+
"quickstart_beta_expert_11": "0x3112c1613eAC3dBAE3D4E38CeF023eb9E2C91CF7",
|
|
86
|
+
"quickstart_beta_expert_12": "0xF4a75F476801B3fBB2e7093aCDcc3576593Cc1fc",
|
|
87
|
+
"quickstart_beta_expert_15_mech_marketplace": "0x88eB38FF79fBa8C19943C0e5Acfa67D5876AdCC1",
|
|
88
|
+
"quickstart_beta_expert_16_mech_marketplace": "0x6c65430515c70a3f5E62107CC301685B7D46f991",
|
|
89
|
+
"quickstart_beta_expert_17_mech_marketplace": "0x1430107A785C3A36a0C1FC0ee09B9631e2E72aFf",
|
|
90
|
+
"quickstart_beta_expert_18_mech_marketplace": "0x041e679d04Fc0D4f75Eb937Dea729Df09a58e454",
|
|
91
|
+
"pearl_beta_mech_marketplace_1": "0xAb10188207Ea030555f53C8A84339A92f473aa5e",
|
|
92
|
+
"pearl_beta_mech_marketplace_2": "0x8d7bE092d154b01d404f1aCCFA22Cef98C613B5D",
|
|
93
|
+
"pearl_beta_mech_marketplace_3": "0x9D00A0551F20979080d3762005C9B74D7Aa77b85",
|
|
94
|
+
"pearl_beta_mech_marketplace_4": "0xE2f80659dB1069f3B6a08af1A62064190c119543",
|
|
95
|
+
"quickstart_beta_mech_marketplace_expert_1": "0xdB9E2713c3dA3C403F2eA6E570eB978b00304e9E",
|
|
96
|
+
"quickstart_beta_mech_marketplace_expert_2": "0x1E90522b45c771DCF5f79645B9e96551d2ECaF62",
|
|
97
|
+
"quickstart_beta_mech_marketplace_expert_3": "0x75EECA6207be98cAc3fDE8a20eCd7B01e50b3472",
|
|
98
|
+
"quickstart_beta_mech_marketplace_expert_4": "0x9c7F6103e3a72E4d1805b9C683Ea5B370Ec1a99f",
|
|
99
|
+
"quickstart_beta_mech_marketplace_expert_5": "0xcdC603e0Ee55Aae92519f9770f214b2Be4967f7d",
|
|
100
|
+
"quickstart_beta_mech_marketplace_expert_6": "0x22D6cd3d587D8391C3aAE83a783f26c67ab54A85",
|
|
101
|
+
"quickstart_beta_mech_marketplace_expert_7": "0xaaEcdf4d0CBd6Ca0622892Ac6044472f3912A5f3",
|
|
102
|
+
"quickstart_beta_mech_marketplace_expert_8": "0x168aED532a0CD8868c22Fc77937Af78b363652B1",
|
|
103
|
+
"quickstart_beta_mech_marketplace_expert_9": "0xdDa9cD214F12e7C2D58E871404A0A3B1177065C8",
|
|
104
|
+
"quickstart_beta_mech_marketplace_expert_10": "0x53a38655B4e659eF4C7F88A26fbF5c67932C7156",
|
|
105
|
+
"mech_marketplace": "0x998dEFafD094817EF329f6dc79c703f1CF18bC90",
|
|
106
|
+
"marketplace_supply_alpha": "0xCAbD0C941E54147D40644CF7DA7e36d70DF46f44",
|
|
107
|
+
"marketplace_demand_alpha_1": "0x9d6e7aB0B5B48aE5c146936147C639fEf4575231",
|
|
108
|
+
"marketplace_demand_alpha_2": "0x9fb17E549FefcCA630dd92Ea143703CeE4Ea4340",
|
|
109
|
+
},
|
|
110
|
+
Chain.OPTIMISM: {
|
|
111
|
+
"optimus_alpha_1": "0x88996bbdE7f982D93214881756840cE2c77C4992",
|
|
112
|
+
"optimus_alpha_2": "0xBCA056952D2A7a8dD4A002079219807CFDF9fd29",
|
|
113
|
+
"optimus_alpha_3": "0x0f69f35652B1acdbD769049334f1AC580927E139",
|
|
114
|
+
"optimus_alpha_4": "0x6891Cf116f9a3bDbD1e89413118eF81F69D298C3",
|
|
115
|
+
},
|
|
116
|
+
Chain.ETHEREUM: {},
|
|
117
|
+
Chain.BASE: {
|
|
118
|
+
"meme_base_alpha_2": "0xc653622FD75026a020995a1d8c8651316cBBc4dA",
|
|
119
|
+
"meme_base_beta": "0x6011E09e7c095e76980b22498d69dF18EB62BeD8",
|
|
120
|
+
"meme_base_beta_2": "0xfb7669c3AdF673b3A545Fa5acd987dbfdA805e22",
|
|
121
|
+
"meme_base_beta_3": "0xCA61633b03c54F64b6A7F1f9A9C0A6Feb231Cc4D",
|
|
122
|
+
"marketplace_supply_alpha": "0xB14Cd66c6c601230EA79fa7Cc072E5E0C2F3A756",
|
|
123
|
+
"marketplace_demand_alpha_1": "0x38Eb3838Dab06932E7E1E965c6F922aDfE494b88",
|
|
124
|
+
"marketplace_demand_alpha_2": "0xBE6E12364B549622395999dB0dB53f163994D7AF",
|
|
125
|
+
"agents_fun_1": "0x2585e63df7BD9De8e058884D496658a030b5c6ce",
|
|
126
|
+
"agents_fun_2": "0x26FA75ef9Ccaa60E58260226A71e9d07564C01bF",
|
|
127
|
+
"agents_fun_3": "0x4D4233EBF0473Ca8f34d105A6256A2389176F0Ce",
|
|
128
|
+
},
|
|
129
|
+
Chain.CELO: {
|
|
130
|
+
"meme_celo_alpha_2": "0x95D12D193d466237Bc1E92a1a7756e4264f574AB",
|
|
131
|
+
},
|
|
132
|
+
Chain.MODE: {
|
|
133
|
+
"optimus_alpha": "0x5fc25f50E96857373C64dC0eDb1AbCBEd4587e91",
|
|
134
|
+
"modius_alpha": "0x534C0A05B6d4d28d5f3630D6D74857B253cf8332",
|
|
135
|
+
"modius_alpha_2": "0xeC013E68FE4B5734643499887941eC197fd757D0",
|
|
136
|
+
"modius_alpha_3": "0x9034D0413D122015710f1744A19eFb1d7c2CEB13",
|
|
137
|
+
"modius_alpha_4": "0x8BcAdb2c291C159F9385964e5eD95a9887302862",
|
|
138
|
+
},
|
|
139
|
+
Chain.POLYGON: {},
|
|
36
140
|
}
|
|
37
141
|
|
|
38
|
-
|
|
39
|
-
|
|
142
|
+
|
|
143
|
+
DEFAULT_PRIORITY_MECH = { # maps mech marketplace address to its default priority mech address and service id
|
|
144
|
+
"0x4554fE75c1f5576c1d7F765B2A036c199Adae329": (
|
|
145
|
+
"0x552cEA7Bc33CbBEb9f1D90c1D11D2C6daefFd053",
|
|
146
|
+
975,
|
|
147
|
+
),
|
|
148
|
+
"0x735FAAb1c4Ec41128c367AFb5c3baC73509f70bB": (
|
|
149
|
+
"0xC05e7412439bD7e91730a6880E18d5D5873F632C",
|
|
150
|
+
2182,
|
|
151
|
+
),
|
|
40
152
|
}
|
|
41
153
|
|
|
42
|
-
|
|
43
|
-
|
|
154
|
+
|
|
155
|
+
# ERC20 token addresses
|
|
156
|
+
OLAS: t.Dict[Chain, str] = {
|
|
157
|
+
Chain.ARBITRUM_ONE: "0x064F8B858C2A603e1b106a2039f5446D32dc81c1",
|
|
158
|
+
Chain.BASE: "0x54330d28ca3357F294334BDC454a032e7f353416",
|
|
159
|
+
Chain.CELO: "0xaCFfAe8e57Ec6E394Eb1b41939A8CF7892DbDc51",
|
|
160
|
+
Chain.ETHEREUM: "0x0001A500A6B18995B03f44bb040A5fFc28E45CB0",
|
|
161
|
+
Chain.GNOSIS: "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f",
|
|
162
|
+
Chain.MODE: "0xcfD1D50ce23C46D3Cf6407487B2F8934e96DC8f9",
|
|
163
|
+
Chain.OPTIMISM: "0xFC2E6e6BCbd49ccf3A5f029c79984372DcBFE527",
|
|
164
|
+
Chain.POLYGON: "0xFEF5d947472e72Efbb2E388c730B7428406F2F95",
|
|
44
165
|
}
|
|
166
|
+
|
|
167
|
+
USDC: t.Dict[Chain, str] = {
|
|
168
|
+
Chain.ARBITRUM_ONE: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
|
169
|
+
Chain.BASE: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
170
|
+
Chain.CELO: "0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
|
|
171
|
+
Chain.ETHEREUM: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
172
|
+
Chain.GNOSIS: "0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83",
|
|
173
|
+
Chain.MODE: "0xd988097fb8612cc24eeC14542bC03424c656005f",
|
|
174
|
+
Chain.OPTIMISM: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
|
|
175
|
+
Chain.POLYGON: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
WRAPPED_NATIVE_ASSET = {
|
|
179
|
+
Chain.ARBITRUM_ONE: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
180
|
+
Chain.BASE: "0x4200000000000000000000000000000000000006",
|
|
181
|
+
Chain.CELO: "0x471EcE3750Da237f93B8E339c536989b8978a438", # Dual token
|
|
182
|
+
Chain.ETHEREUM: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
|
183
|
+
Chain.GNOSIS: "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d",
|
|
184
|
+
Chain.MODE: "0x4200000000000000000000000000000000000006",
|
|
185
|
+
Chain.OPTIMISM: "0x4200000000000000000000000000000000000006",
|
|
186
|
+
Chain.POLYGON: "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
ERC20_TOKENS = {
|
|
190
|
+
"OLAS": OLAS,
|
|
191
|
+
"USDC": USDC,
|
|
192
|
+
"WRAPPED_NATIVE": WRAPPED_NATIVE_ASSET,
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
DUST = {
|
|
196
|
+
Chain.ARBITRUM_ONE: int(1e14),
|
|
197
|
+
Chain.BASE: int(1e14),
|
|
198
|
+
Chain.CELO: int(1e15),
|
|
199
|
+
Chain.ETHEREUM: int(1e14),
|
|
200
|
+
Chain.GNOSIS: int(1e15),
|
|
201
|
+
Chain.MODE: int(1e14),
|
|
202
|
+
Chain.OPTIMISM: int(1e14),
|
|
203
|
+
Chain.POLYGON: int(1e14),
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
DEFAULT_NEW_SAFE_FUNDS: t.Dict[Chain, t.Dict[str, int]] = {
|
|
207
|
+
Chain.ARBITRUM_ONE: {
|
|
208
|
+
ZERO_ADDRESS: int(1e15 / 4),
|
|
209
|
+
},
|
|
210
|
+
Chain.BASE: {
|
|
211
|
+
ZERO_ADDRESS: int(1e15 / 4),
|
|
212
|
+
},
|
|
213
|
+
Chain.CELO: {
|
|
214
|
+
ZERO_ADDRESS: int(1e18),
|
|
215
|
+
},
|
|
216
|
+
Chain.ETHEREUM: {
|
|
217
|
+
ZERO_ADDRESS: int(1e15 / 4),
|
|
218
|
+
},
|
|
219
|
+
Chain.GNOSIS: {
|
|
220
|
+
ZERO_ADDRESS: int(1e18),
|
|
221
|
+
},
|
|
222
|
+
Chain.MODE: {
|
|
223
|
+
ZERO_ADDRESS: int(1e15 / 4),
|
|
224
|
+
},
|
|
225
|
+
Chain.OPTIMISM: {
|
|
226
|
+
ZERO_ADDRESS: int(1e15 / 4),
|
|
227
|
+
},
|
|
228
|
+
Chain.POLYGON: {
|
|
229
|
+
ZERO_ADDRESS: int(1e18),
|
|
230
|
+
},
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
DEFAULT_EOA_TOPUPS = {
|
|
234
|
+
Chain.ARBITRUM_ONE: {ZERO_ADDRESS: 2_500_000_000_000_000},
|
|
235
|
+
Chain.BASE: {ZERO_ADDRESS: 2_500_000_000_000_000},
|
|
236
|
+
Chain.CELO: {ZERO_ADDRESS: 750_000_000_000_000_000},
|
|
237
|
+
Chain.ETHEREUM: {ZERO_ADDRESS: 10_000_000_000_000_000},
|
|
238
|
+
Chain.GNOSIS: {ZERO_ADDRESS: 750_000_000_000_000_000},
|
|
239
|
+
Chain.MODE: {ZERO_ADDRESS: 250_000_000_000_000},
|
|
240
|
+
Chain.OPTIMISM: {ZERO_ADDRESS: 2_500_000_000_000_000},
|
|
241
|
+
Chain.POLYGON: {ZERO_ADDRESS: 750_000_000_000_000_000},
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
DEFAULT_EOA_TOPUPS_WITHOUT_SAFE = {
|
|
245
|
+
chain: {asset: amount * 2 for asset, amount in amounts.items()}
|
|
246
|
+
for chain, amounts in DEFAULT_EOA_TOPUPS.items()
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
DEFAULT_RECOVERY_TOPUPS = {
|
|
250
|
+
Chain.ARBITRUM_ONE: {ZERO_ADDRESS: 625_000_000_000_000},
|
|
251
|
+
Chain.BASE: {ZERO_ADDRESS: 625_000_000_000_000},
|
|
252
|
+
Chain.CELO: {ZERO_ADDRESS: 187_500_000_000_000_000},
|
|
253
|
+
Chain.ETHEREUM: {ZERO_ADDRESS: 2_500_000_000_000_000},
|
|
254
|
+
Chain.GNOSIS: {ZERO_ADDRESS: 187_500_000_000_000_000},
|
|
255
|
+
Chain.MODE: {ZERO_ADDRESS: 62_500_000_000_000},
|
|
256
|
+
Chain.OPTIMISM: {ZERO_ADDRESS: 625_000_000_000_000},
|
|
257
|
+
Chain.POLYGON: {ZERO_ADDRESS: 187_500_000_000_000_000},
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
DEFAULT_EOA_THRESHOLD = 0.5
|
|
261
|
+
|
|
262
|
+
EXPLORER_URL = {
|
|
263
|
+
Chain.ARBITRUM_ONE: {
|
|
264
|
+
"tx": "https://arbiscan.io/tx/{tx_hash}",
|
|
265
|
+
"address": "https://arbiscan.io/address/{address}",
|
|
266
|
+
},
|
|
267
|
+
Chain.BASE: {
|
|
268
|
+
"tx": "https://basescan.org/tx/{tx_hash}",
|
|
269
|
+
"address": "https://basescan.org/address/{address}",
|
|
270
|
+
},
|
|
271
|
+
Chain.CELO: {
|
|
272
|
+
"tx": "https://celoscan.io/tx/{tx_hash}",
|
|
273
|
+
"address": "https://celoscan.io/address/{address}",
|
|
274
|
+
},
|
|
275
|
+
Chain.ETHEREUM: {
|
|
276
|
+
"tx": "https://etherscan.io/tx/{tx_hash}",
|
|
277
|
+
"address": "https://etherscan.io/address/{address}",
|
|
278
|
+
},
|
|
279
|
+
Chain.GNOSIS: {
|
|
280
|
+
"tx": "https://gnosisscan.io/tx/{tx_hash}",
|
|
281
|
+
"address": "https://gnosisscan.io/address/{address}",
|
|
282
|
+
},
|
|
283
|
+
Chain.MODE: {
|
|
284
|
+
"tx": "https://explorer.mode.network/tx/{tx_hash}",
|
|
285
|
+
"address": "https://explorer.mode.network/address/{address}",
|
|
286
|
+
},
|
|
287
|
+
Chain.OPTIMISM: {
|
|
288
|
+
"tx": "https://optimistic.etherscan.io/tx/{tx_hash}",
|
|
289
|
+
"address": "https://optimistic.etherscan.io/address/{address}",
|
|
290
|
+
},
|
|
291
|
+
Chain.POLYGON: {
|
|
292
|
+
"tx": "https://polygonscan.com/tx/{tx_hash}",
|
|
293
|
+
"address": "https://polygonscan.com/address/{address}",
|
|
294
|
+
},
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
@cache
|
|
299
|
+
def get_asset_name(chain: Chain, asset_address: str) -> str:
|
|
300
|
+
"""Get token name."""
|
|
301
|
+
if asset_address == ZERO_ADDRESS:
|
|
302
|
+
return get_currency_denom(chain)
|
|
303
|
+
|
|
304
|
+
if WRAPPED_NATIVE_ASSET.get(chain) == asset_address:
|
|
305
|
+
return f"W{get_currency_denom(chain)}"
|
|
306
|
+
|
|
307
|
+
for symbol, tokens in ERC20_TOKENS.items():
|
|
308
|
+
if tokens.get(chain) == asset_address:
|
|
309
|
+
return symbol
|
|
310
|
+
|
|
311
|
+
return asset_address
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
@cache
|
|
315
|
+
def get_asset_decimals(chain: Chain, asset_address: str) -> int:
|
|
316
|
+
"""Get token decimals."""
|
|
317
|
+
if asset_address == ZERO_ADDRESS:
|
|
318
|
+
return NATIVE_CURRENCY_DECIMALS
|
|
319
|
+
erc20_token = registry_contracts.erc20.get_instance(
|
|
320
|
+
ledger_api=get_default_ledger_api(chain),
|
|
321
|
+
contract_address=asset_address,
|
|
322
|
+
)
|
|
323
|
+
return erc20_token.functions.decimals().call()
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def format_asset_amount(
|
|
327
|
+
chain: Chain, asset_address: str, amount: int, precision: int = 4
|
|
328
|
+
) -> str:
|
|
329
|
+
"""Convert smallest unit to human-readable string with token symbol."""
|
|
330
|
+
decimals = get_asset_decimals(chain, asset_address)
|
|
331
|
+
symbol = get_asset_name(chain, asset_address)
|
|
332
|
+
value = amount / (10**decimals)
|
|
333
|
+
return f"{value:.{precision}f} {symbol}"
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
# TODO: Deprecate in favour of StakingManager method
|
|
337
|
+
def get_staking_contract(
|
|
338
|
+
chain: str, staking_program_id: t.Optional[str]
|
|
339
|
+
) -> t.Optional[str]:
|
|
340
|
+
"""Get staking contract based on the config and the staking program."""
|
|
341
|
+
if staking_program_id == NO_STAKING_PROGRAM_ID or staking_program_id is None:
|
|
342
|
+
return None
|
|
343
|
+
|
|
344
|
+
return STAKING[Chain(chain)].get(
|
|
345
|
+
staking_program_id,
|
|
346
|
+
staking_program_id,
|
|
347
|
+
)
|