mirror of https://github.com/nucypher/nucypher.git
(Almost) Completes UserEscrow Agency Methods
parent
46c0e96d81
commit
c5c8a6f9cb
|
@ -178,19 +178,19 @@ class Deployer(NucypherTokenActor):
|
|||
self.deploy_miner_contract(secret=miner_secret)
|
||||
self.deploy_policy_contract(secret=policy_secret)
|
||||
|
||||
def deploy_beneficiary_contracts(self, allocations: List[Dict[str, Union[str, int]]]):
|
||||
def deploy_beneficiary_contracts(self, allocations: List[Dict[str, Union[str, int]]]) -> None:
|
||||
"""
|
||||
|
||||
Example allocation dataset:
|
||||
Example allocation dataset (one year is 31540000 seconds):
|
||||
|
||||
data = [{'address': '0xdeadbeef', 'amount': 100, 'periods': 100},
|
||||
{'address': '0xabced120', 'amount': 133432, 'periods': 1},
|
||||
{'address': '0xf7aefec2', 'amount': 999, 'periods': 30}]
|
||||
data = [{'address': '0xdeadbeef', 'amount': 100, 'duration': 31540000},
|
||||
{'address': '0xabced120', 'amount': 133432, 'duration': 31540000*2},
|
||||
{'address': '0xf7aefec2', 'amount': 999, 'duration': 31540000*3}]
|
||||
"""
|
||||
for allocation in allocations:
|
||||
deployer = self.deploy_user_escrow()
|
||||
deployer.deliver(value=allocation['amount'],
|
||||
duration=allocation['periods'],
|
||||
duration=allocation['duration'],
|
||||
beneficiary_address=allocation['address'])
|
||||
|
||||
@staticmethod
|
||||
|
@ -330,9 +330,9 @@ class Miner(NucypherTokenActor):
|
|||
return bool(self.locked_tokens > 0)
|
||||
|
||||
@property
|
||||
def locked_tokens(self, ):
|
||||
def locked_tokens(self):
|
||||
"""Returns the amount of tokens this miner has locked."""
|
||||
return self.miner_agent.get_locked_tokens(node_address=self.checksum_public_address)
|
||||
return self.miner_agent.get_locked_tokens(miner_address=self.checksum_public_address)
|
||||
|
||||
@property
|
||||
def stakes(self) -> Tuple[list]:
|
||||
|
|
|
@ -115,9 +115,16 @@ class MinerAgent(EthereumContractAgent):
|
|||
# MinersEscrow Contract API
|
||||
#
|
||||
|
||||
def get_locked_tokens(self, node_address):
|
||||
"""Returns the amount of tokens this miner has locked."""
|
||||
return self.contract.functions.getLockedTokens(node_address).call()
|
||||
def get_locked_tokens(self, miner_address: str, periods: int = 0) -> int:
|
||||
"""
|
||||
Returns the amount of tokens this miner has locked.
|
||||
|
||||
TODO: Validate input (periods not less then 0)
|
||||
"""
|
||||
return self.contract.functions.getLockedTokens(miner_address, periods).call()
|
||||
|
||||
def owned_tokens(self, address: str) -> int:
|
||||
return self.contract.functions.minerInfo(address).call()[0]
|
||||
|
||||
def get_stake_info(self, miner_address: str, stake_index: int):
|
||||
first_period, *others, locked_value = self.contract.functions.getStakeInfo(miner_address, stake_index).call()
|
||||
|
@ -152,7 +159,11 @@ class MinerAgent(EthereumContractAgent):
|
|||
return txhash
|
||||
|
||||
def mint(self, node_address) -> Tuple[str, str]:
|
||||
"""Computes reward tokens for the miner's account"""
|
||||
"""
|
||||
Computes reward tokens for the miner's account;
|
||||
This is only used to calculate the reward for the final period of a stake,
|
||||
when you intend to withdraw 100% of tokens.
|
||||
"""
|
||||
|
||||
mint_txhash = self.contract.functions.mint().transact({'from': node_address})
|
||||
self.blockchain.wait_for_receipt(mint_txhash)
|
||||
|
@ -231,12 +242,12 @@ class PolicyAgent(EthereumContractAgent):
|
|||
author_address: str,
|
||||
value: int,
|
||||
periods: int,
|
||||
reward: int,
|
||||
initial_reward: int,
|
||||
node_addresses: List[str]) -> str:
|
||||
|
||||
txhash = self.contract.functions.createPolicy(policy_id,
|
||||
periods,
|
||||
reward,
|
||||
initial_reward,
|
||||
node_addresses).transact({'from': author_address,
|
||||
'value': value})
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
|
@ -315,8 +326,6 @@ class UserEscrowAgent(EthereumContractAgent):
|
|||
self.__read_proxy()
|
||||
super().__init__(blockchain=self.blockchain, contract=self.principal_contract, *args, **kwargs)
|
||||
|
||||
self.token_agent = NucypherTokenAgent(blockchain=self.blockchain)
|
||||
|
||||
def __read_proxy(self):
|
||||
self.__proxy_agent = self.UserEscrowProxyAgent(blockchain=self.blockchain)
|
||||
contract = self.__proxy_agent._generate_beneficiary_agency(principal_address=self.principal_contract.address)
|
||||
|
@ -353,7 +362,6 @@ class UserEscrowAgent(EthereumContractAgent):
|
|||
|
||||
@property
|
||||
def proxy_contract(self):
|
||||
"""Directly reference the beneficiary's deployed contract instead of the proxy contracts's interface"""
|
||||
if self.__proxy_contract is NO_CONTRACT_AVAILABLE:
|
||||
raise RuntimeError("{} not available".format(self.registry_contract_name))
|
||||
return self.__proxy_contract
|
||||
|
@ -366,31 +374,18 @@ class UserEscrowAgent(EthereumContractAgent):
|
|||
return self.__principal_contract
|
||||
|
||||
@property
|
||||
def allocation(self):
|
||||
return self.principal_contract.functions.lockedValue().call()
|
||||
|
||||
@property
|
||||
def end_timestamp(self):
|
||||
return self.principal_contract.functions.endLockTimestamp().call()
|
||||
|
||||
@property
|
||||
def locked_tokens(self) -> int:
|
||||
"""Returns the amount of tokens this miner has locked for the beneficiary."""
|
||||
def allocation(self) -> int:
|
||||
return self.principal_contract.functions.getLockedTokens().call()
|
||||
|
||||
@property
|
||||
def end_timestamp(self) -> int:
|
||||
return self.principal_contract.functions.endLockTimestamp().call()
|
||||
|
||||
def lock(self, amount: int, periods: int) -> str:
|
||||
txhash = self.__proxy_contract.functions.lock(amount, periods).transact({'from': self.__beneficiary})
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
return txhash
|
||||
|
||||
def deposit_tokens(self, amount: int, sender_address: str):
|
||||
"""Deposit without locking"""
|
||||
txhash = self.token_agent.transfer(amount=amount,
|
||||
sender_address=sender_address,
|
||||
target_address=self.principal_contract.address)
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
return txhash
|
||||
|
||||
def withdraw_tokens(self, value: int) -> str:
|
||||
txhash = self.principal_contract.functions.withdrawTokens(value).transact({'from': self.__beneficiary})
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
|
@ -410,3 +405,23 @@ class UserEscrowAgent(EthereumContractAgent):
|
|||
txhash = self.__proxy_contract.functions.withdrawAsMiner(value).transact({'from': self.__beneficiary})
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
return txhash
|
||||
|
||||
def confirm_activity(self) -> str:
|
||||
txhash = self.__proxy_contract.functions.confirmActivity().transact({'from': self.__beneficiary})
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
return txhash
|
||||
|
||||
def mint(self) -> str:
|
||||
txhash = self.__proxy_contract.functions.mint().transact({'from': self.__beneficiary})
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
return txhash
|
||||
|
||||
def collect_policy_reward(self) -> str:
|
||||
txhash = self.__proxy_contract.functions.withdrawPolicyReward().transact({'from': self.__beneficiary})
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
return txhash
|
||||
|
||||
def set_min_reward_rate(self, rate: int) -> str:
|
||||
txhash = self.__proxy_contract.functions.setMinRewardRate(rate).transact({'from': self.__beneficiary})
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
return txhash
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
"""Nucypher Token and Miner constants."""
|
||||
|
||||
ONE_YEAR_IN_SECONDS = 31540000
|
||||
NUCYPHER_GAS_LIMIT = 5000000 # TODO: move elsewhere?
|
||||
|
||||
#
|
||||
|
|
|
@ -21,7 +21,6 @@ class ContractDeployer:
|
|||
agency = NotImplemented
|
||||
_contract_name = NotImplemented
|
||||
_interface_class = BlockchainDeployerInterface
|
||||
__is_proxy = False
|
||||
__upgradeable = NotImplemented
|
||||
__proxy_deployer = NotImplemented
|
||||
|
||||
|
@ -40,6 +39,7 @@ class ContractDeployer:
|
|||
self.__armed = False
|
||||
self.__proxy_contract = NotImplemented
|
||||
self.__deployer_address = deployer_address
|
||||
self.__ready_to_deploy = False
|
||||
|
||||
@property
|
||||
def contract_address(self) -> str:
|
||||
|
@ -68,7 +68,8 @@ class ContractDeployer:
|
|||
def is_armed(self) -> bool:
|
||||
return bool(self.__armed is True)
|
||||
|
||||
def check_ready_to_deploy(self, fail=False, check_arming=False) -> Tuple[bool, list]:
|
||||
@property
|
||||
def ready_to_deploy(self, fail=False, check_arming=False) -> Tuple[bool, list]:
|
||||
"""
|
||||
Iterates through a set of rules required for an ethereum
|
||||
contract deployer to be eligible for deployment returning a
|
||||
|
@ -80,6 +81,9 @@ class ContractDeployer:
|
|||
If fail is set to True, raise a configuration error, instead of returning.
|
||||
"""
|
||||
|
||||
if self.__ready_to_deploy is True:
|
||||
return True, list()
|
||||
|
||||
rules = [
|
||||
(self.is_deployed is not True, 'Contract already deployed'),
|
||||
(self.deployer_address is not None, 'No deployer address set.'),
|
||||
|
@ -111,7 +115,7 @@ class ContractDeployer:
|
|||
|
||||
return True
|
||||
|
||||
def arm(self, abort=True) -> tuple:
|
||||
def arm(self, abort=True) -> bool:
|
||||
"""
|
||||
Safety mechanism for ethereum contract deployment
|
||||
|
||||
|
@ -124,8 +128,8 @@ class ContractDeployer:
|
|||
"""
|
||||
if self.__armed is True and abort is True:
|
||||
raise self.ContractDeploymentError('{} deployer is already armed.'.format(self._contract_name))
|
||||
self.__armed, disqualifications = self.check_ready_to_deploy(fail=abort, check_arming=False)
|
||||
return self.__armed, disqualifications
|
||||
self.__armed, disqualifications = self.ready_to_deploy
|
||||
return self.__armed
|
||||
|
||||
def deploy(self) -> dict:
|
||||
"""
|
||||
|
@ -158,7 +162,7 @@ class NucypherTokenDeployer(ContractDeployer):
|
|||
The contract must be armed before it can be deployed.
|
||||
Deployment can only ever be executed exactly once!
|
||||
"""
|
||||
self.check_ready_to_deploy(fail=True, check_arming=True)
|
||||
self.ready_to_deploy
|
||||
|
||||
_contract, deployment_txhash = self.blockchain.interface.deploy_contract(
|
||||
self._contract_name,
|
||||
|
@ -175,7 +179,6 @@ class DispatcherDeployer(ContractDeployer):
|
|||
"""
|
||||
|
||||
_contract_name = 'Dispatcher'
|
||||
__is_proxy = True
|
||||
__upgradeable = False
|
||||
|
||||
def __init__(self, target_contract: Contract, secret_hash: bytes, *args, **kwargs):
|
||||
|
@ -228,7 +231,7 @@ class MinerEscrowDeployer(ContractDeployer):
|
|||
"""
|
||||
|
||||
# Raise if not all-systems-go
|
||||
self.check_ready_to_deploy(fail=True, check_arming=True)
|
||||
self.ready_to_deploy
|
||||
|
||||
# Build deployment arguments
|
||||
origin_args = {'from': self.deployer_address}
|
||||
|
@ -307,7 +310,7 @@ class PolicyManagerDeployer(ContractDeployer):
|
|||
self.secret_hash = secret_hash
|
||||
|
||||
def deploy(self) -> Dict[str, str]:
|
||||
self.check_ready_to_deploy(fail=True, check_arming=True)
|
||||
self.ready_to_deploy
|
||||
|
||||
# Creator deploys the policy manager
|
||||
policy_manager_contract, deploy_txhash = self.blockchain.interface.deploy_contract(
|
||||
|
@ -352,8 +355,6 @@ class PolicyManagerDeployer(ContractDeployer):
|
|||
class LibraryLinkerDeployer(ContractDeployer):
|
||||
|
||||
_contract_name = 'UserEscrowLibraryLinker'
|
||||
__is_proxy = True
|
||||
__upgradeable = False
|
||||
|
||||
def __init__(self, target_contract: Contract, secret_hash: bytes, *args, **kwargs):
|
||||
self.target_contract = target_contract
|
||||
|
@ -370,8 +371,6 @@ class LibraryLinkerDeployer(ContractDeployer):
|
|||
class UserEscrowProxyDeployer(ContractDeployer):
|
||||
|
||||
_contract_name = 'UserEscrowProxy'
|
||||
__is_proxy = True
|
||||
__upgradeable = True
|
||||
__proxy_deployer = LibraryLinkerDeployer
|
||||
|
||||
def __init__(self, secret_hash: bytes, *args, **kwargs):
|
||||
|
@ -418,7 +417,7 @@ class UserEscrowDeployer(ContractDeployer):
|
|||
|
||||
agency = UserEscrowAgent
|
||||
_contract_name = agency.registry_contract_name
|
||||
__proxy_deployer = UserEscrowProxyDeployer
|
||||
__linker_deployer = LibraryLinkerDeployer
|
||||
__allocation_registry = AllocationRegistry
|
||||
|
||||
def __init__(self, allocation_registry: AllocationRegistry = None, *args, **kwargs) -> None:
|
||||
|
@ -500,12 +499,12 @@ class UserEscrowDeployer(ContractDeployer):
|
|||
def deploy(self) -> dict:
|
||||
"""Deploy a new instance of UserEscrow to the blockchain."""
|
||||
|
||||
self.check_ready_to_deploy(fail=True, check_arming=True)
|
||||
self.ready_to_deploy
|
||||
|
||||
deployment_transactions = dict()
|
||||
proxy_contract = self.__proxy_deployer.get_latest_version(blockchain=self.blockchain)
|
||||
|
||||
args = (self._contract_name, proxy_contract.address, self.token_agent.contract_address)
|
||||
linker_contract = self.blockchain.interface.get_contract_by_name(name=self.__linker_deployer._contract_name)
|
||||
args = (self._contract_name, linker_contract.address, self.token_agent.contract_address)
|
||||
user_escrow_contract, deploy_txhash = self.blockchain.interface.deploy_contract(*args, enroll=False)
|
||||
self.__principal_contract = user_escrow_contract
|
||||
deployment_transactions['deploy_user_escrow'] = deploy_txhash
|
||||
|
|
|
@ -206,7 +206,7 @@ class BlockchainInterface:
|
|||
if uri_breakdown.scheme == 'tester':
|
||||
|
||||
if uri_breakdown.netloc == 'pyevm':
|
||||
genesis_params = PyEVMBackend._generate_genesis_params(overrides={'gas_limit': NUCYPHER_GAS_LIMIT})
|
||||
genesis_params = PyEVMBackend.generate_genesis_params(overrides={'gas_limit': NUCYPHER_GAS_LIMIT})
|
||||
pyevm_backend = PyEVMBackend(genesis_parameters=genesis_params)
|
||||
eth_tester = EthereumTester(backend=pyevm_backend, auto_mine_transactions=True)
|
||||
provider = EthereumTesterProvider(ethereum_tester=eth_tester)
|
||||
|
|
Loading…
Reference in New Issue