mirror of https://github.com/nucypher/nucypher.git
deprecates agent.call() and .transact(); Upgrade to newer web3 API, with direct contract access
parent
f9eb10de60
commit
4ec9df051f
|
@ -67,7 +67,7 @@ class Miner(TokenActor):
|
|||
def __update_locked_tokens(self) -> None:
|
||||
"""Query the contract for the amount of locked tokens on this miner's eth address and cache it"""
|
||||
|
||||
self.__locked_tokens = self.miner_agent.read().getLockedTokens(self.address)
|
||||
self.__locked_tokens = self.miner_agent.contract.functions.getLockedTokens(self.address).call()
|
||||
|
||||
@property
|
||||
def is_staking(self):
|
||||
|
@ -86,7 +86,7 @@ class Miner(TokenActor):
|
|||
def _approve_escrow(self, amount: int) -> str:
|
||||
"""Approve the transfer of token from the miner's address to the escrow contract."""
|
||||
|
||||
txhash = self.token_agent.transact({'from': self.address}).approve(self.miner_agent.contract_address, amount)
|
||||
txhash = self.token_agent.contract.functions.approve(self.miner_agent.contract_address, amount).transact({'from': self.address})
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
|
||||
self._transactions.append((datetime.utcnow(), txhash))
|
||||
|
@ -96,7 +96,7 @@ class Miner(TokenActor):
|
|||
def _send_tokens_to_escrow(self, amount, locktime) -> str:
|
||||
"""Send tokes to the escrow from the miner's address"""
|
||||
|
||||
deposit_txhash = self.miner_agent.transact({'from': self.address}).deposit(amount, locktime)
|
||||
deposit_txhash = self.miner_agent.contract.functions.deposit(amount, locktime).transact({'from': self.address})
|
||||
self.blockchain.wait_for_receipt(deposit_txhash)
|
||||
|
||||
self._transactions.append((datetime.utcnow(), deposit_txhash))
|
||||
|
@ -111,11 +111,17 @@ class Miner(TokenActor):
|
|||
return approve_txhash, deposit_txhash
|
||||
|
||||
# TODO add divide_stake method
|
||||
def switch_lock(self):
|
||||
lock_txhash = self.miner_agent.contract.functions.switchLock().transact({'from': self.address})
|
||||
self.blockchain.wait_for_receipt(lock_txhash)
|
||||
|
||||
self._transactions.append((datetime.utcnow(), lock_txhash))
|
||||
return lock_txhash
|
||||
|
||||
def _confirm_activity(self) -> str:
|
||||
"""Miner rewarded for every confirmed period"""
|
||||
|
||||
txhash = self.miner_agent.transact({'from': self.address}).confirmActivity()
|
||||
txhash = self.miner_agent.contract.functions.confirmActivity().transact({'from': self.address})
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
|
||||
self._transactions.append((datetime.utcnow(), txhash))
|
||||
|
@ -125,8 +131,8 @@ class Miner(TokenActor):
|
|||
def mint(self) -> Tuple[str, str]:
|
||||
"""Computes and transfers tokens to the miner's account"""
|
||||
|
||||
confirm_txhash = self.miner_agent.transact({'from': self.address, 'gas_price': 0}).confirmActivity()
|
||||
mint_txhash = self.miner_agent.transact({'from': self.address, 'gas_price': 0}).mint()
|
||||
confirm_txhash = self.miner_agent.contract.functions.confirmActivity().transact({'from': self.address, 'gas_price': 0})
|
||||
mint_txhash = self.miner_agent.contract.functions.mint().transact({'from': self.address, 'gas_price': 0})
|
||||
|
||||
self.blockchain.wait_for_receipt(mint_txhash)
|
||||
self._transactions.append((datetime.utcnow(), mint_txhash))
|
||||
|
@ -136,7 +142,7 @@ class Miner(TokenActor):
|
|||
def collect_policy_reward(self, policy_manager):
|
||||
"""Collect rewarded ETH"""
|
||||
|
||||
policy_reward_txhash = policy_manager.transact({'from': self.address}).withdraw()
|
||||
policy_reward_txhash = policy_manager.contract.functions.withdraw().transact({'from': self.address})
|
||||
self.blockchain.wait_for_receipt(policy_reward_txhash)
|
||||
|
||||
self._transactions.append((datetime.utcnow(), policy_reward_txhash))
|
||||
|
@ -146,11 +152,14 @@ class Miner(TokenActor):
|
|||
def collect_staking_reward(self) -> str:
|
||||
"""Withdraw tokens rewarded for staking."""
|
||||
|
||||
token_amount = self.miner_agent.read().minerInfo(self.address)[self.miner_agent.MinerInfo.VALUE.value]
|
||||
token_amount_bytes = self.miner_agent.contract.functions.getMinerInfo(self.miner_agent.MinerInfo.VALUE.value,
|
||||
self.address, 0).call()
|
||||
|
||||
token_amount = self.blockchain._chain.web3.toInt(token_amount_bytes)
|
||||
|
||||
# reward_amount = TODO
|
||||
|
||||
reward_txhash = self.miner_agent.transact({'from': self.address}).withdraw(token_amount)
|
||||
reward_txhash = self.miner_agent.contract.functions.withdraw(token_amount).transact({'from': self.address})
|
||||
|
||||
self.blockchain.wait_for_receipt(reward_txhash)
|
||||
self._transactions.append((datetime.utcnow(), reward_txhash))
|
||||
|
@ -172,7 +181,11 @@ class Miner(TokenActor):
|
|||
raise self.StakingError('Locktime must be at least {}'.format(min_stake_time))
|
||||
|
||||
if entire_balance is True:
|
||||
amount = self.miner_agent.read().minerInfo(self.address)[self.miner_agent.MinerInfo.VALUE.value]
|
||||
|
||||
balance_bytes = self.miner_agent.contract.functions.getMinerInfo(self.miner_agent.MinerInfo.VALUE.value,
|
||||
self.address, 0).call()
|
||||
|
||||
amount = self.blockchain._chain.web3.toInt(balance_bytes)
|
||||
else:
|
||||
if not amount > 0:
|
||||
raise self.StakingError('Staking amount must be greater than zero.')
|
||||
|
@ -185,7 +198,7 @@ class Miner(TokenActor):
|
|||
def publish_data(self, data) -> str:
|
||||
"""Store new data"""
|
||||
|
||||
txhash = self.miner_agent.transact({'from': self.address}).setMinerId(data)
|
||||
txhash = self.miner_agent.contract.functions.setMinerId(data).transact({'from': self.address})
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
|
||||
self._transactions.append((datetime.utcnow(), txhash))
|
||||
|
@ -195,12 +208,17 @@ class Miner(TokenActor):
|
|||
def fetch_data(self) -> tuple:
|
||||
"""Retrieve all asosciated contract data for this miner."""
|
||||
|
||||
count = self.miner_agent.read().getMinerIdsLength(self.address)
|
||||
count_bytes = self.miner_agent.contract.functions.getMinerInfo(self.miner_agent.MinerInfo.MINER_IDS_LENGTH.value,
|
||||
self.address, 0).call()
|
||||
|
||||
count = self.blockchain._chain.web3.toInt(count_bytes)
|
||||
|
||||
miner_ids = list()
|
||||
for index in range(count):
|
||||
miner_id = self.miner_agent.read().getMinerId(self.address, index)
|
||||
miner_ids.append(miner_id)
|
||||
miner_id = self.miner_agent.contract.functions.getMinerInfo(self.miner_agent.MinerInfo.MINER_ID.value,
|
||||
self.address, index).call()
|
||||
encoded_miner_id = miner_id.encode('latin-1')
|
||||
miner_ids.append(encoded_miner_id)
|
||||
|
||||
return tuple(miner_ids)
|
||||
|
||||
|
|
|
@ -24,19 +24,23 @@ class EthereumContractAgent(ABC):
|
|||
self.blockchain = blockchain
|
||||
|
||||
address = blockchain.provider.get_contract_address(contract_name=self._principal_contract_name)[-1] # TODO
|
||||
self._contract = blockchain.provider.get_contract(address)
|
||||
self.__contract = blockchain.provider.get_contract(address)
|
||||
|
||||
def __repr__(self):
|
||||
class_name = self.__class__.__name__
|
||||
r = "{}(blockchain={}, contract={})"
|
||||
return r.format(class_name, self.blockchain, self._contract)
|
||||
return r.format(class_name, self.blockchain, self.__contract)
|
||||
|
||||
def __eq__(self, other):
|
||||
return bool(self.contract_address == other.contract_address)
|
||||
|
||||
@property
|
||||
def contract(self):
|
||||
return self.__contract
|
||||
|
||||
@property
|
||||
def contract_address(self):
|
||||
return self._contract.address
|
||||
return self.__contract.address
|
||||
|
||||
@property
|
||||
def contract_name(self) -> str:
|
||||
|
@ -46,28 +50,11 @@ class EthereumContractAgent(ABC):
|
|||
def origin(self) -> str:
|
||||
return self.blockchain.provider.w3.eth.coinbase # TODO: make swappable
|
||||
|
||||
def read(self):
|
||||
"""
|
||||
Returns an object that exposes the contract instance functions.
|
||||
|
||||
This method is intended for use with method chaining,
|
||||
results in zero state changes, and costs zero gas.
|
||||
Useful as a dry-run before sending an actual transaction.
|
||||
|
||||
See more on interacting with contract instances in the Populus docs:
|
||||
http://populus.readthedocs.io/en/latest/dev_cycle.part-07.html#call-an-instance-function
|
||||
"""
|
||||
return self._contract.call()
|
||||
|
||||
def transact(self, payload: dict):
|
||||
"""Packs kwargs into payload dictionary and transmits an eth contract transaction"""
|
||||
return self._contract.transact(payload)
|
||||
|
||||
def get_balance(self, address: str=None) -> int:
|
||||
"""Get the balance of a token address, or of this contract address"""
|
||||
if address is None:
|
||||
address = self.contract_address
|
||||
return self.read().balanceOf(address)
|
||||
return self.contract.functions.balanceOf(address).call()
|
||||
|
||||
|
||||
class NucypherTokenAgent(EthereumContractAgent):
|
||||
|
@ -117,10 +104,16 @@ class MinerAgent(EthereumContractAgent):
|
|||
Miner addresses will be returned in the order in which they were added to the MinersEscrow's ledger
|
||||
"""
|
||||
|
||||
count = self.read().getMinersLength()
|
||||
info_reader = partial(self.contract.functions.getMinerInfo,
|
||||
self.MinerInfo.MINERS_LENGTH.value, self._deployer._null_addr
|
||||
# ___,
|
||||
)
|
||||
|
||||
count_bytes = info_reader(0).call()
|
||||
count = self.blockchain.provider.w3.toInt(count_bytes)
|
||||
for index in range(count):
|
||||
yield self.read().miners(index)
|
||||
addr = info_reader(index).call()
|
||||
yield self.blockchain.provider.w3.toChecksumAddress(addr)
|
||||
|
||||
def sample(self, quantity: int=10, additional_ursulas: float=1.7, attempts: int=5, duration: int=10) -> List[str]:
|
||||
"""
|
||||
|
@ -147,7 +140,7 @@ class MinerAgent(EthereumContractAgent):
|
|||
|
||||
system_random = random.SystemRandom()
|
||||
n_select = round(quantity*additional_ursulas) # Select more Ursulas
|
||||
n_tokens = self.read().getAllLockedTokens()
|
||||
n_tokens = self.contract.functions.getAllLockedTokens().call()
|
||||
|
||||
if not n_tokens > 0:
|
||||
raise self.NotEnoughUrsulas('There are no locked tokens.')
|
||||
|
@ -158,7 +151,7 @@ class MinerAgent(EthereumContractAgent):
|
|||
|
||||
addrs, addr, index, shift = set(), self._deployer._null_addr, 0, 0
|
||||
for delta in deltas:
|
||||
addr, index, shift = self.read().findCumSum(index, delta + shift, duration)
|
||||
addr, index, shift = self.contract.functions.findCumSum(index, delta + shift, duration).call()
|
||||
addrs.add(addr)
|
||||
|
||||
if len(addrs) >= quantity:
|
||||
|
@ -173,7 +166,7 @@ class PolicyAgent(EthereumContractAgent):
|
|||
_principal_contract_name = PolicyManagerDeployer._contract_name
|
||||
|
||||
def fetch_arrangement_data(self, arrangement_id: bytes) -> list:
|
||||
blockchain_record = self.read().policies(arrangement_id)
|
||||
blockchain_record = self.contract.functions.policies(arrangement_id).call()
|
||||
return blockchain_record
|
||||
|
||||
def revoke_arrangement(self, arrangement_id: bytes, author, gas_price: int):
|
||||
|
@ -181,6 +174,6 @@ class PolicyAgent(EthereumContractAgent):
|
|||
Revoke by arrangement ID; Only the policy author can revoke the policy
|
||||
"""
|
||||
|
||||
txhash = self.transact({'from': author.address, 'gas_price': gas_price}).revokePolicy(arrangement_id)
|
||||
txhash = self.contract.functions.revokePolicy(arrangement_id).transact({'from': author.address, 'gas_price': gas_price})
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
return txhash
|
||||
|
|
|
@ -257,7 +257,7 @@ class MinerEscrowDeployer(ContractDeployer, NuCypherMinerConfig):
|
|||
the_escrow_contract = wrapped_escrow_contract
|
||||
|
||||
# 3 - Transfer tokens to the miner escrow #
|
||||
reward_txhash = self.token_agent.transact(origin_args).transfer(the_escrow_contract.address, self.remaining_supply)
|
||||
reward_txhash = self.token_agent.contract.functions.transfer(the_escrow_contract.address, self.remaining_supply).transact(origin_args)
|
||||
_reward_receipt = self.blockchain.wait_for_receipt(reward_txhash)
|
||||
|
||||
# 4 - Initialize the Miner Escrow contract
|
||||
|
@ -314,8 +314,8 @@ class PolicyManagerDeployer(ContractDeployer):
|
|||
the_policy_manager_contract = wrapped_policy_manager_contract
|
||||
|
||||
# Configure the MinerEscrow by setting the PolicyManager
|
||||
policy_setter_txhash = self.miner_agent.transact({'from': self.token_agent.origin}).\
|
||||
setPolicyManager(the_policy_manager_contract.address)
|
||||
policy_setter_txhash = self.miner_agent.contract.functions. \
|
||||
setPolicyManager(the_policy_manager_contract.address).transact({'from': self.token_agent.origin})
|
||||
|
||||
self.blockchain.wait_for_receipt(policy_setter_txhash)
|
||||
|
||||
|
|
|
@ -6,7 +6,9 @@ from nucypher.blockchain.eth.agents import MinerAgent
|
|||
|
||||
|
||||
@pytest.mark.skip("Last 5 stubborn blockchain tests.")
|
||||
def test_miner_locking_tokens(chain, mock_token_deployer, mock_miner_agent):
|
||||
def test_miner_locking_tokens(chain, token_agent, mock_token_deployer, mock_miner_agent):
|
||||
|
||||
chain._token_airdrop(token_agent=token_agent, amount=10000)
|
||||
|
||||
miner = Miner(miner_agent=mock_miner_agent, address=chain.provider.w3.eth.accounts[1])
|
||||
|
||||
|
@ -14,16 +16,16 @@ def test_miner_locking_tokens(chain, mock_token_deployer, mock_miner_agent):
|
|||
miner.stake(amount=an_amount_of_tokens, locktime=mock_miner_agent._deployer._min_locked_periods)
|
||||
|
||||
# Verify that the escrow is allowed to receive tokens
|
||||
# assert mock_miner_agent.token_agent.read().allowance(miner.address, mock_miner_agent.contract_address) == 0
|
||||
assert mock_miner_agent.token_agent.contract.functions.allowance(miner.address, mock_miner_agent.contract_address).call() == 0
|
||||
|
||||
# Stake starts after one period
|
||||
# assert miner.token_balance() == 0
|
||||
# assert mock_miner_agent.read().getLockedTokens(miner.address) == 0
|
||||
assert miner.token_balance() == 0
|
||||
assert mock_miner_agent.contract.functions.getLockedTokens(miner.address).call() == 0
|
||||
|
||||
# Wait for it...
|
||||
chain.time_travel(mock_miner_agent._deployer._hours_per_period)
|
||||
|
||||
assert mock_miner_agent.read().getLockedTokens(miner.address) == an_amount_of_tokens
|
||||
assert mock_miner_agent.contract.functions.getLockedTokens(miner.address).call() == an_amount_of_tokens
|
||||
|
||||
|
||||
@pytest.mark.skip("Last 5 stubborn blockchain tests.")
|
||||
|
@ -60,10 +62,10 @@ def test_mine_then_withdraw_tokens(chain, mock_token_deployer, token_agent, mock
|
|||
assert miner.locked_tokens == half_of_stake
|
||||
|
||||
# Ensure the MinerEscrow contract is allowed to receive tokens form Alice
|
||||
# assert miner.token_agent.read().allowance(miner.address, miner.miner_agent.contract_address) == half_of_stake
|
||||
# assert miner.token_agent.contract.functions.allowance(miner.address, miner.miner_agent.contract_address).call() == half_of_stake
|
||||
|
||||
# Blockchain staking starts after one period
|
||||
# assert mock_miner_agent.read().getAllLockedTokens() == 0
|
||||
# assert mock_miner_agent.contract.functions.getAllLockedTokens().call() == 0
|
||||
|
||||
# Wait for it...
|
||||
# chain.wait_time(2)
|
||||
|
@ -139,6 +141,9 @@ def test_publish_miner_datastore(chain, mock_miner_agent):
|
|||
assert len(stored_miner_ids) == 2
|
||||
assert another_mock_miner_id == stored_miner_ids[1]
|
||||
|
||||
supposedly_the_same_miner_id = mock_miner_agent.read().getMinerId(miner_addr, 1)
|
||||
supposedly_the_same_miner_id = mock_miner_agent.contract.functions \
|
||||
.getMinerInfo(mock_miner_agent._deployer.MinerInfoField.MINER_ID.value,
|
||||
miner_addr, 1).call()
|
||||
|
||||
assert another_mock_miner_id == supposedly_the_same_miner_id
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ def test_token_deployer_and_agent(chain):
|
|||
assert len(token_agent.contract_address) == 42
|
||||
|
||||
# Check that the token contract has tokens
|
||||
assert token_agent.read().totalSupply() != 0
|
||||
assert token_agent.contract.functions.totalSupply().call() != 0
|
||||
# assert token().totalSupply() == int(1e9) * _M # TODO
|
||||
|
||||
# Retrieve the token from the blockchain
|
||||
|
|
Loading…
Reference in New Issue