Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get rid of the dotmap and generate Munches for multsigs and extras too. #72

Merged
merged 13 commits into from
Jul 27, 2023
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 0.8.0
Added extra Munch based explorable dotmaps + permissions
Restructured function returns to be more consistent.
# 0.6.0
Use new balancer deployments repo.
# 0.4.0
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ init:
pip install -r bal_addresses/requirements.txt
pip install -r bal_addresses/requirements-dev.txt
ci:
pytest
pytest
5 changes: 3 additions & 2 deletions bal_addresses/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .addresses import AddrBook
from .permissions import BalPermissions
from .addresses import AddrBook, GITHUB_DEPLOYMENTS_RAW, GITHUB_DEPLOYMENTS_NICE, GITHUB_RAW_OUTPUTS, GITHUB_RAW_EXTRAS
from .permissions import BalPermissions
from .errors import MultipleMatchesError, NoResultError
107 changes: 79 additions & 28 deletions bal_addresses/addresses.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
from .errors import MultipleMatchesError, NoResultError
from typing import Dict
from typing import Optional

Expand All @@ -20,28 +21,24 @@
GITHUB_RAW_OUTPUTS = (
"https://raw.githubusercontent.com/BalancerMaxis/bal_addresses/main/outputs"
)
GITHUB_RAW_EXTRAS = (
"https://raw.githubusercontent.com/BalancerMaxis/bal_addresses/main/extras"
)
ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"


class MultipleMatchesError(Exception):
pass


class NoResultError(Exception):
pass

class AddrBook:

fullbook = requests.get(f"{GITHUB_RAW_OUTPUTS}/addressbook.json").json()
chains = Munch(requests.get(
chains = Munch.fromDict(requests.get(
"https://raw.githubusercontent.com/BalancerMaxis/bal_addresses/main/extras/chains.json"
).json())
CHAIN_IDS_BY_NAME = chains["CHAIN_IDS_BY_NAME"]
fx_description_by_name = DotMap(requests.get(
fx_description_by_name = Munch.fromDict(requests.get(
"https://raw.githubusercontent.com/BalancerMaxis/bal_addresses/main/extras/func_desc_by_name.json"
).json())
GITHUB_MONOREPO_RAW = (
"https://raw.githubusercontent.com/balancer-labs/balancer-v2-monorepo/master"
)
chain_ids_by_name = chains.CHAIN_IDS_BY_NAME

def __init__(self, chain, jsonfile=False):
self.jsonfile = jsonfile
Expand All @@ -56,16 +53,18 @@ def __init__(self, chain, jsonfile=False):
dactive = deployments["active"][chain]
except Exception:
dactive = {}
self.deployments_only = DotMap(dactive | dold)
self.deployments_only = Munch.fromDict(dactive | dold)
try:
self.flatbook = requests.get(f"{GITHUB_RAW_OUTPUTS}/{chain}.json").json()
self.reversebook = DotMap(
requests.get(f"{GITHUB_RAW_OUTPUTS}/{chain}_reverse.json").json())
self.reversebook = requests.get(f"{GITHUB_RAW_OUTPUTS}/{chain}_reverse.json").json()
except Exception:
self.flatbook = {"zero/zero": ZERO_ADDRESS}
self.reversebook = {ZERO_ADDRESS: "zero/zero"}

self._deployments = None
self._extras = None
self._multisigs = None


@property
def deployments(self) -> Optional[Munch]:
Expand All @@ -76,9 +75,30 @@ def deployments(self) -> Optional[Munch]:
return self._deployments
else:
self.populate_deployments()

return self._deployments

@property
def extras(self) -> Optional[Munch]:
"""
Get the extras for all chains in a form of a Munch object
"""
if self._extras is not None:
return self._extras
else:
self.populate_extras()
Tritium-VLK marked this conversation as resolved.
Show resolved Hide resolved
return self._extras

@property
def multisigs(self) -> Optional[Munch]:
"""
Get the multisigs for all chains in a form of a Munch object
"""
if self._multisigs is not None:
return self._multisigs
else:
self.populate_multisigs()
Tritium-VLK marked this conversation as resolved.
Show resolved Hide resolved
return self._extras

def populate_deployments(self) -> None:
chain_deployments = requests.get(
f"{GITHUB_DEPLOYMENTS_RAW}/addresses/{self.chain}.json"
Expand All @@ -104,31 +124,58 @@ def _process_deployment(self, deployment: Dict) -> Dict:
processed_deployment[deployment_identifier] = v
return processed_deployment


def populate_extras(self) -> None:
chain_extras = requests.get(
f"{GITHUB_RAW_EXTRAS}/{self.chain}.json"
)
if chain_extras.ok:
self._extras = Munch.fromDict(chain_extras.json())


def populate_multisigs(self) -> None:
msigs = requests.get(
f"{GITHUB_RAW_EXTRAS}/multisigs.json"
).json()
if msigs.get(self.chain):
self._multisigs = Munch.fromDict(msigs[self.chain])
else:
print(f"Warning: No multisigs for chain {self.chain}, multisigs must be added in extras/multisig.json")
self._multisigs = Munch



def search_unique(self, substr):
results = [s for s in self.flatbook.keys() if substr in s]
if len(results) > 1:
raise MultipleMatchesError(f"{substr} Multiple matches found: {results}")
if len(results) < 1:
raise NoResultError(f"{substr}")
return results[0]
return Munch.fromDict({
"path": results[0],
"address": self.flatbook[results[0]]
})

def search_unique_deployment(self, substr):
results = [s for s in self.deployments_only.keys() if substr in s]
if len(results) > 1:
raise self.MultipleMatchesError(f"{substr} Multiple matches found: {results}")
raise MultipleMatchesError(f"{substr} Multiple matches found: {results}")
if len(results) < 1:
raise self.NoResultError(f"{substr}")
return results[0]
raise NoResultError(f"{substr}")
return Munch.fromDict({
"deployment": results[0],
"addresses_by_contract": self.deployments_only[results[0]]
})

def search_many_deployments(self, substr):
search = [s for s in self.deployments_only.keys() if substr in s]
results = {key: self.deployments_only[key] for key in search if key in self.flatbook}
return results
return search

def search_many(self, substr):
search = [s for s in self.flatbook.keys() if substr in s]
results = {key: self.flatbook[key] for key in search if key in self.flatbook}
return results
output = []
results = {path: address for path, address in self.flatbook.items() if substr in path}
outputs = [Munch.fromDict({"path": path, "address": address}) for path, address in results.items()]
return outputs

def latest_contract(self, contract_name):
deployments = []
Expand All @@ -138,7 +185,12 @@ def latest_contract(self, contract_name):
if len(deployments) == 0:
raise NoResultError(contract_name)
deployments.sort(reverse=True)
return self.deployments_only[deployments[0]][contract_name]
address = self.deployments_only[deployments[0]][contract_name]
return Munch.fromDict({
"path": self.reversebook[address],
"address": address
})


@staticmethod
def checksum_address_dict(addresses):
Expand All @@ -161,8 +213,7 @@ def build_dotmap(self):
fullbook = json.load(f)
else:
fullbook = self.fullbook
return (
DotMap(fullbook["active"].get(self.chain, {}) | fullbook["old"].get(self.chain, {})))
return (fullbook["active"].get(self.chain, {}) | fullbook["old"].get(self.chain, {}))
# Checksum one more time for good measure

def flatten_dict(self, d, parent_key='', sep='/'):
Expand All @@ -177,7 +228,7 @@ def flatten_dict(self, d, parent_key='', sep='/'):

def generate_flatbook(self):
print(f"Generating Addressbook for {self.chain}")
ab = dict(self.dotmap)
ab = dict(self.merge_deployments())
return self.flatten_dict(ab)


Expand Down
6 changes: 6 additions & 0 deletions bal_addresses/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

class MultipleMatchesError(Exception):
pass

class NoResultError(Exception):
pass
4 changes: 2 additions & 2 deletions bal_addresses/gen_addresses.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def reverse_dict(d):
inv_map = {v: k for k, v in d.items()}
return inv_map

def write_addressbooks(chainlist=AddrBook.CHAIN_IDS_BY_NAME.keys()):
def write_addressbooks(chainlist=AddrBook.chain_ids_by_name.keys()):
for chain in chainlist:
print(f"Writing addressbooks for {chain}")
flatbook = AddrBook(chain, jsonfile="outputs/addressbook.json").generate_flatbook()
Expand All @@ -18,7 +18,7 @@ def write_addressbooks(chainlist=AddrBook.CHAIN_IDS_BY_NAME.keys()):
json.dump(reverse_dict(flatbook), f, indent=3)

def main():
chains = AddrBook.CHAIN_IDS_BY_NAME.keys()
chains = AddrBook.chain_ids_by_name.keys()
print(f"Generating new addressbook jsons for {chains}")
write_addressbooks(chains)

Expand Down
4 changes: 2 additions & 2 deletions bal_addresses/generate_current_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import json
import pandas as pd
import os
from addresses import AddrBook
from addresses import AddrBook, GITHUB_DEPLOYMENTS_RAW
from permissions import BalPermissions
from web3 import Web3
import datetime
Expand All @@ -29,7 +29,7 @@ def build_chain_permissions_list(chain_name):
r = a.flatbook
results = {}
address_names = a.reversebook
action_ids_list = f"{BalPermissions.GITHUB_DEPLOYMENTS_RAW}/action-ids/{chain_name}/action-ids.json"
action_ids_list = f"{GITHUB_DEPLOYMENTS_RAW}/action-ids/{chain_name}/action-ids.json"
w3 = w3_by_chain[chain_name]
authorizer = w3.eth.contract(address=r["20210418-authorizer/Authorizer"], abi=json.load(open("bal_addresses/abis/Authorizer.json")))
try:
Expand Down
41 changes: 9 additions & 32 deletions bal_addresses/permissions.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,17 @@

import json
from web3 import Web3
from .errors import NoResultError, MultipleMatchesError
import requests
from dotmap import DotMap
from addresses import AddrBook
from bal_addresses import AddrBook, GITHUB_DEPLOYMENTS_RAW, GITHUB_RAW_OUTPUTS
from collections import defaultdict
from munch import Munch

### Errors
class MultipleMatchesError(Exception):
pass


class NoResultError(Exception):
pass


### Main class
class BalPermissions:
GITHUB_DEPLOYMENTS_RAW = "https://raw.githubusercontent.com/balancer/balancer-deployments/master"
## TODO switch back to main branch
#GITHUB_RAW_OUTPUTS = "https://raw.githubusercontent.com/BalancerMaxis/bal_addresses/main/outputs"
GITHUB_RAW_OUTPUTS = "https://raw.githubusercontent.com/BalancerMaxis/bal_addresses/generate_permissions_jsons/outputs"


### Errors
class MultipleMatchesError(Exception):
pass

class NoResultError(Exception):
pass

def __init__(self, chain):
self.chain = chain
self.active_permissions_by_action_id = requests.get(f"{self.GITHUB_RAW_OUTPUTS}/permissions/active/{chain}.json").json()
self.action_ids_by_contract_by_deployment = requests.get(f"{self.GITHUB_DEPLOYMENTS_RAW}/action-ids/{chain}/action-ids.json").json()
self.active_permissions_by_action_id = requests.get(f"{GITHUB_RAW_OUTPUTS}/permissions/active/{chain}.json").json()
self.action_ids_by_contract_by_deployment = requests.get(f"{GITHUB_DEPLOYMENTS_RAW}/action-ids/{chain}/action-ids.json").json()

# Define
self.paths_by_action_id = defaultdict(set)
Expand Down Expand Up @@ -63,7 +40,7 @@ def search_many_paths_by_unique_deployment(self, deployment_substr, fx_substr) -
a = AddrBook(self.chain)
results = []
deployment = a.search_unique_deployment(deployment_substr)
deployment_fxs = self.search_path(deployment)
deployment_fxs = self.search_path(deployment.deployment)
search = [s for s in deployment_fxs if fx_substr in s]
for r in search:
result = DotMap({
Expand All @@ -76,9 +53,9 @@ def search_many_paths_by_unique_deployment(self, deployment_substr, fx_substr) -
def search_unique_path_by_unique_deployment(self, deployment_substr, fx_substr) -> dict[str, str]:
results = self.search_many_paths_by_unique_deployment(deployment_substr, fx_substr)
if len(results) > 1:
raise self.MultipleMatchesError(f"{fx_substr} Multiple matches found: {results}")
raise MultipleMatchesError(f"{fx_substr} Multiple matches found: {results}")
if len(results) < 1:
raise self.NoResultError(f"{fx_substr}")
raise NoResultError(f"{fx_substr}")
return results[0]

def needs_authorizer(self, contract, deployment) -> bool:
Expand All @@ -88,14 +65,14 @@ def allowed_addresses(self, action_id) -> list[str]:
try:
return self.active_permissions_by_action_id[action_id]
except KeyError:
raise self.NoResultError(f"{action_id} has no authorized callers")
raise NoResultError(f"{action_id} has no authorized callers")

def allowed_caller_names(self, action_id) -> list[str]:
a = AddrBook(self.chain)
try:
addresslist = self.active_permissions_by_action_id[action_id]
except KeyError:
raise self.NoResultError(f"{action_id} has no authorized callers")
raise NoResultError(f"{action_id} has no authorized callers")
names = [a.flatbook.get(item, 'undef') for item in addresslist]
return names

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages

VERSION = '0.7.0'
VERSION = '0.8.0'
DESCRIPTION = 'Balancer Maxi Addressbook'
LONG_DESCRIPTION = 'Balancer Maxi Addressbook and Balancer Permissions helper'

Expand Down
Loading
Loading