Relayer Interface Architecture
Each chain is defined by a chain interface and contract interface, which are defined by the following abstract base classes:
class BaseChainInterface(abc.ABC):
"""
Base class for all chain interfaces
Governs transaction retrieval and creation
"""
@abc.abstractmethod
def sign_and_send_transaction(self, tx):
"""
Given a raw transaction, signs it and sends it to the chain
Args:
tx: the raw transaction to be sent to the chain
"""
pass
@abc.abstractmethod
def get_transactions(self, address, height=None):
"""
Retrieves all transactions from the chain that fit interface-dependent filters
"""
pass
@abc.abstractmethod
def get_last_block(self):
"""
Retrieves the current block height of the chain
"""
pass
class BaseContractInterface(abc.ABC):
"""
Base class for all contract interfaces
Governs contract interaction, execution, and event parsing.
"""
address = None
@abc.abstractmethod
def call_function(self, function_name, *args):
"""
Given a function in a contract, and the arguments to that function,
calls it on chain
Args:
function_name: the name of the contract function to call
*args: the (potentially many) arguments to pass to that function
"""
pass
@abc.abstractmethod
def parse_event_from_txn(self, event_name, txn) -> List[Task]:
"""
Given a transaction, outputs all the events of a particular name
that were emitted in that transaction
Args:
event_name: the event to look for
txn: the transaction to parse
Returns: a list of Tasks corresponding to the events
"""
pass
Any chain that implements these python interfaces can connect to the relayer, by modifying the config generation function, the current implementation of which is given below:
def generate_eth_config(config_dict, provider=None):
"""
Converts a config dict into a tuple of (chain_interface, contract_interface, event_name, function_name)
for ethereum
Args:
config_dict: a dict containing contract address, contract schema, and wallet address
provider: an optional API client
Returns: the relevant tuple of chain, contract, event, and function
"""
priv_key = bytes.fromhex(os.environ['ethereum-private-key'])
address = config_dict['wallet_address']
contract_address = config_dict['contract_address']
contract_schema = config_dict['contract_schema']
event_name = 'logNewTask'
function_name = 'postExecution'
initialized_chain = EthInterface(private_key=priv_key, address=address, provider=provider)
initialized_contract = EthContract(interface=initialized_chain, address=contract_address,
abi=contract_schema)
eth_tuple = (initialized_chain, initialized_contract, event_name, function_name)
return eth_tuple
def generate_scrt_config(config_dict, provider=None):
"""
Converts a config dict into a tuple of (chain_interface, contract_interface, event_name, function_name)
for secret
Args:
config_dict: a dict containing contract address, contract schema, and wallet address
provider: an optional API client
Returns: the relevant tuple of chain, contract, event, and function
"""
priv_key = bytes.fromhex(os.environ['secret-private-key'])
address = config_dict['wallet_address']
contract_address = config_dict['contract_address']
with open(f'{Path(__file__).parent.absolute()}/secret_abi.json') as f:
contract_schema = f.read()
event_name = 'wasm'
function_name = list(json.loads(contract_schema).keys())[0]
initialized_chain = SCRTInterface(private_key=priv_key, address=address, provider=provider)
initialized_contract = SCRTContract(interface=initialized_chain, address=contract_address,
abi=contract_schema)
scrt_tuple = (initialized_chain, initialized_contract, event_name, function_name)
return scrt_tuple
def generate_full_config(config_file, provider_pair=None):
"""
Takes in a yaml filepath and generates a config dict for eth and scrt relays
Args:
config_file: the path to the relevant config file
provider_pair: a pair of scrt and eth providers, optional
Returns:
a dict mapping scrt and eth to their respective configs
"""
with open(config_file) as f:
config_dict = safe_load(f)
if provider_pair is None:
provider_eth, provider_scrt = None, None
else:
provider_eth, provider_scrt = provider_pair
eth_config = generate_eth_config(config_dict['ethereum'], provider=provider_eth)
scrt_config = generate_scrt_config(config_dict['secret'], provider=provider_scrt)
keys_dict = {'secret': {'verification': config_dict['secret']['contract_eth_address'],
'encryption': config_dict['secret']['contract_encryption_key']}}
return {'ethereum': eth_config, 'secret': scrt_config}, keys_dict
Last updated