Optional allowance detection for TokenAgency to ease stake init on the same address multiple times.

pull/1124/head
Kieran Prasch 2019-07-02 10:18:07 -07:00
parent d55a63fe74
commit ce9002fccd
No known key found for this signature in database
GPG Key ID: 199AB839D4125A62
2 changed files with 53 additions and 5 deletions

View File

@ -32,7 +32,8 @@ from constant_sorrow.constants import (
NO_FUNDING_ACCOUNT
)
from eth_tester.exceptions import TransactionFailed
from eth_utils import keccak, is_checksum_address
from eth_utils import is_checksum_address
from eth_utils import keccak
from twisted.logger import Logger
from web3 import Web3
@ -724,9 +725,21 @@ class StakeHolder(BaseConfiguration):
self.__get_accounts()
if sync_now:
if sync_now and not offline_mode:
self.read_onchain_stakes() # Stakes
def __str__(self) -> str:
r = f'{self.__class__.__name__}(funding_account={self.funding_account})'
return r
def __repr__(self) -> str:
r = f'{self.__class__.__name__}(funding_account={self.funding_account})'
return r
#
# Configuration
#
def static_payload(self) -> dict:
"""Values to read/write from stakeholder JSON configuration files"""
payload = dict(provider_uri=self.blockchain.provider_uri,
@ -757,6 +770,18 @@ class StakeHolder(BaseConfiguration):
self.__transacting_powers[checksum_address] = transacting_power
transacting_power.activate(password=password)
def to_configuration_file(self, *args, **kwargs) -> str:
filepath = super().to_configuration_file(modifier=self.funding_account, *args, **kwargs)
return filepath
def connect(self, blockchain: BlockchainInterface = None) -> None:
"""Go Online"""
if not self.staking_agent:
self.staking_agent = StakingEscrowAgent(blockchain=blockchain)
if not self.token_agent:
self.token_agent = NucypherTokenAgent(blockchain=blockchain)
self.blockchain = self.token_agent.blockchain
#
# Account Utilities
#
@ -916,7 +941,9 @@ class StakeHolder(BaseConfiguration):
# Send new staker account NU
_result = self.token_agent.transfer(amount=amount.to_nunits(),
sender_address=self.funding_account,
target_address=staker.checksum_address)
target_address=staker.checksum_address,
auto_approve=True)
return staker
def initialize_stake(self,
amount: NU,
@ -967,6 +994,13 @@ class StakeHolder(BaseConfiguration):
self.to_configuration_file(override=True)
return receipts
def calculate_rewards(self) -> dict:
rewards = dict()
for staker in self.stakers:
reward = staker.calculate_reward()
rewards[staker.checksum_address] = reward
return rewards
def collect_rewards(self,
staker_address: str,
password: str,

View File

@ -124,6 +124,12 @@ class NucypherTokenAgent(EthereumContractAgent, metaclass=Agency):
address = address if address is not None else self.contract_address
return self.contract.functions.balanceOf(address).call()
def increase_allowance(self, sender_address: str, target_address: str, increase: int):
contract_function = self.contract.functions.increaseAllowance(target_address, increase)
receipt = self.blockchain.send_transaction(transaction_function=contract_function,
sender_address=sender_address)
return receipt
def approve_transfer(self, amount: int, target_address: str, sender_address: str):
"""Approve the transfer of token from the sender address to the target address."""
payload = {'gas': 500_000} # TODO #413: gas needed for use with geth.
@ -133,8 +139,16 @@ class NucypherTokenAgent(EthereumContractAgent, metaclass=Agency):
sender_address=sender_address)
return receipt
def transfer(self, amount: int, target_address: str, sender_address: str):
self.approve_transfer(amount=amount, target_address=target_address, sender_address=sender_address)
def transfer(self, amount: int, target_address: str, sender_address: str, auto_approve: bool = True):
if auto_approve:
allowance = self.contract.functions.allowance(sender_address, target_address).call()
if allowance != 0:
delta = int(amount) - int(allowance)
self.increase_allowance(sender_address=sender_address,
target_address=target_address,
increase=delta)
else:
self.approve_transfer(amount=amount, target_address=target_address, sender_address=sender_address)
contract_function = self.contract.functions.transfer(target_address, amount)
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=sender_address)
return receipt