def test_add_stake_success(setup_chain): coldkeypair = Keypair.create_from_uri("//Alice") hotkeypair = Keypair.create_from_mnemonic(Keypair.generate_mnemonic()) wallet = generate_wallet(coldkey_pair=coldkeypair, hotkey_pair=hotkeypair) subtensor = connect(setup_chain) # Subscibe the hotkey using Alice's cold key, which has TAO subscribe(subtensor, wallet) uid = subtensor.get_uid_for_pubkey(hotkeypair.public_key) assert uid is not None result = subtensor.get_stake_for_uid(uid) assert int(result) == int(Balance(0)) # Get balance balance_pre = subtensor.get_balance(coldkeypair.ss58_address) # Timeout is 30, because 3 * blocktime does not work. result = subtensor.add_stake(wallet, Balance(4000), hotkeypair.public_key, wait_for_finalization=True, timeout=30) assert result == True # Check if the amount of stake end up in the hotkey account result = subtensor.get_stake_for_uid(uid) assert int(result) == int(Balance(4000)) # Check if the balances had reduced by the amount of stake balance_post = subtensor.get_balance(coldkeypair.ss58_address) assert int(balance_post) == int(balance_pre) - 4000
def test_unstake_success(setup_chain): coldkeypair = Keypair.create_from_uri('//Alice') hotkey_pair = Keypair.create_from_mnemonic(Keypair.generate_mnemonic()) wallet = generate_wallet(coldkey_pair=coldkeypair, hotkey_pair=hotkey_pair) subtensor = connect(setup_chain) subscribe(subtensor, wallet) # Get the balance for the cold key, we use this for later comparison balance = subtensor.get_balance(coldkeypair.public_key) add_stake(subtensor, wallet, Balance(4000)) result = subtensor.unstake(amount=Balance(3000), wallet=wallet, hotkey_id=hotkey_pair.public_key, wait_for_finalization=True, timeout=30) assert result is True # We have staked 4000, but unstaked 3000, so the balance should be 1000 less than before the staking operation new_balance = subtensor.get_balance(coldkeypair.ss58_address) assert int(new_balance) == int(balance) - 1000 uid = subtensor.get_uid_for_pubkey(hotkey_pair.public_key) stake = subtensor.get_stake_for_uid(uid) # When staked, this node will receive the full block reward. # We need to ignore this effect, hence the mod operator assert int(stake) % BLOCK_REWARD == 1000
def test_add_stake_success(setup_chain): coldkey = Keypair.create_from_uri("//Alice") hotkey = Keypair.create_from_uri('//Alice') wallet = generate_wallet(coldkey=coldkey, hotkey=hotkey) subtensor = setup_subtensor(setup_chain) # Register the hotkey using Alice's cold key subtensor.register(wallet=wallet) uid = subtensor.get_uid_for_hotkey(hotkey.ss58_address) assert uid is not None # Verify the node has 0 stake result = wallet.get_stake(subtensor=subtensor) assert result == Balance(0) # Get balance. This should be default account balance value of Alice (1152921504606846976) balance_pre = subtensor.get_balance(coldkey.ss58_address) add_stake(subtensor, wallet, 100) # # Check if the amount of stake ends up in the hotkey account result = wallet.get_stake(subtensor=subtensor) assert result == Balance.from_tao(100) # Check if the balances had reduced by the amount of stake balance_post = subtensor.get_balance(coldkey.ss58_address) assert balance_post == Balance( int(balance_pre) - PARTIAL_FEE - int(Balance.from_tao(100)))
def get_stake_for_uid(self, uid) -> Balance: r""" Returns the staked token amount of the peer with the passed uid. Args: uid (int): Uid to query for metadata. Returns: stake (int): Amount of staked token. """ stake = self.substrate.get_runtime_state(module='SubtensorModule', storage_function='Stake', params=[uid]) result = stake['result'] if not result: return Balance(0) return Balance(result)
def transfer(self): r""" Transfers token of amount to dest. """ self.subtensor.connect() amount = Balance.from_float(self.config.amount) balance = self.subtensor.get_balance(self.wallet.coldkey.ss58_address) if balance < amount: print( colored( "Not enough balance ({}) to transfer {}".format( balance, amount), 'red')) quit() print( colored( "Requesting transfer of {}, from coldkey: {} to dest: {}". format(amount.rao, self.wallet.coldkey.public_key, dest), 'blue')) print(colored("Waiting for finalization...", 'white')) result = self.subtensor.transfer(self.config.dest, amount, wait_for_finalization=True, timeout=bittensor.__blocktime__ * 5) if result: print( colored( "Transfer finalized with amount: {} Tao to dest: {} from coldkey.pub: {}" .format(amount.tao, self.config.dest, self.wallet.coldkey.public_key), 'green')) else: print(colored("Transfer failed", 'red'))
def unstake( self, amount_tao: int, uid: int ): r""" Unstaked token of amount to from uid. """ self.wallet.assert_coldkey() self.wallet.assert_coldkeypub() self.subtensor.connect() unstaking_balance = Balance.from_float( amount_tao ) neurons = self._associated_neurons() neuron = neurons.get_by_uid( uid ) if not neuron: logger.log('USER-CRITICAL', "Neuron with uid: {} is not associated with coldkey.pub: {}".format( uid, self.wallet.coldkey.public_key)) quit() neuron.stake = self.subtensor.get_stake_for_uid(neuron.uid) if unstaking_balance > neuron.stake: logger.log('USER-CRITICAL', "Neuron with uid: {} does not have enough stake ({}) to be able to unstake {}".format( uid, neuron.stake, unstaking_balance)) quit() logger.log('USER-ACTION', "Requesting unstake of \u03C4{} from hotkey: {} to coldkey: {}".format(unstaking_balance.tao, neuron.hotkey, self.wallet.coldkey.public_key)) logger.log('USER-INFO', "Waiting for finalization...") result = self.subtensor.unstake ( wallet = self.wallet, amount = unstaking_balance, hotkey_id = neuron.hotkey, wait_for_finalization = True, timeout = bittensor.__blocktime__ * 5 ) if result: logger.log('USER-SUCCESS', "Unstaked: \u03C4{} from uid:{} to coldkey.pub:{}".format(unstaking_balance.tao, neuron.uid, self.wallet.coldkey.public_key)) else: logger.log('USER-CRITICAL', "Unstaking transaction failed")
def stake( self, amount_tao: int, uid: int ): r""" Stakes token of amount to hotkey uid. """ self.wallet.assert_coldkey() self.wallet.assert_coldkeypub() self.subtensor.connect() staking_balance = Balance.from_float( amount_tao ) account_balance = self.subtensor.get_balance( self.wallet.coldkey.ss58_address ) if account_balance < staking_balance: logger.log('USER-CRITICAL', "Not enough balance (\u03C4{}) to stake \u03C4{}".format(account_balance, staking_balance)) quit() neurons = self._associated_neurons() neuron = neurons.get_by_uid( uid ) if not neuron: logger.log('USER-CRITICAL', "Neuron with uid: {} is not associated with coldkey.pub: {}".format( uid, self.wallet.coldkey.public_key )) quit() logger.log('USER-ACTION', "Adding stake of \u03C4{} from coldkey {} to hotkey {}".format( staking_balance.tao, self.wallet.coldkey.public_key, neuron.hotkey)) logger.log('USER-INFO', "Waiting for finalization...") result = self.subtensor.add_stake ( wallet = self.wallet, amount = staking_balance, hotkey_id = neuron.hotkey, wait_for_finalization = True, timeout = bittensor.__blocktime__ * 5 ) if result: logger.log('USER-SUCCESS', "Staked: \u03C4{} to uid: {} from coldkey.pub: {}".format( staking_balance.tao, uid, self.wallet.coldkey.public_key )) else: logger.log('USER-CRITICAL', "Stake transaction failed")
def stake( self ): r""" Stakes token of amount to hotkey uid. """ self.wallet.assert_coldkey() self.wallet.assert_coldkeypub() self.wallet.assert_hotkey() self.subtensor.connect() amount = Balance.from_float( self.config.amount ) balance = self.subtensor.get_balance( self.wallet.coldkey.ss58_address ) if balance < amount: print(colored("Not enough balance ({}) to stake {}".format(balance, amount), 'red')) quit() neurons = self._associated_neurons() neuron = neurons.get_by_uid( self.config.uid ) if not neuron: print(colored("Neuron with uid: {} is not associated with coldkey.pub: {}".format(self.config.uid, self.wallet.coldkey.public_key), 'red')) quit() print(colored("Adding stake of {} rao from coldkey {} to hotkey {}".format(amount.rao, self.wallet.coldkey.public_key, neuron.hotkey), 'blue')) print(colored("Waiting for finalization...", 'white')) result = self.subtensor.add_stake( amount, neuron.hotkey, wait_for_finalization = True, timeout = bittensor.__blocktime__ * 5) if result: print(colored("Staked: {} Tao to uid: {} from coldkey.pub: {}".format(amount.tao, self.config.uid, self.wallet.coldkey.public_key), 'green')) else: print(colored("Stake transaction failed", 'red'))
def unstake( self ): r""" Unstaked token of amount to from uid. """ self.wallet.assert_coldkey() self.wallet.assert_coldkeypub() self.wallet.assert_hotkey() self.subtensor.connect() amount = Balance.from_float( self.config.amount ) neurons = self._associated_neurons() neuron = neurons.get_by_uid( self.config.uid ) if not neuron: print(colored("Neuron with uid: {} is not associated with coldkey.pub: {}".format( self.config.uid, self.wallet.coldkey.public_key), 'red')) quit() neuron.stake = self.subtensor.get_stake_for_uid(neuron.uid) if amount > neuron.stake: print(colored("Neuron with uid: {} does not have enough stake ({}) to be able to unstake {}".format( self.config.uid, neuron.stake, amount), 'red')) quit() print(colored("Requesting unstake of {} rao for hotkey: {} to coldkey: {}".format(amount.rao, neuron.hotkey, self.wallet.coldkey.public_key), 'blue')) print(colored("Waiting for finalization...", 'white')) result = self.subtensor.unstake(amount, neuron.hotkey, wait_for_finalization = True, timeout = bittensor.__blocktime__ * 5) if result: print(colored("Unstaked:{} from uid:{} to coldkey.pub:{}".format(amount.tao, neuron.uid, self.wallet.coldkey.public_key), 'green')) else: print(colored("Unstaking transaction failed", 'red'))
def transfer( self, amount_tao: int, destination: str): r""" Transfers token of amount to dest. """ self.wallet.assert_coldkey() self.wallet.assert_coldkeypub() self.subtensor.connect() transfer_balance = Balance.from_float( amount_tao ) acount_balance = self.subtensor.get_balance(self.wallet.coldkey.ss58_address) if acount_balance < transfer_balance: logger.log('USER-CRITICAL', "Not enough balance (\u03C4{}) to transfer \u03C4{}".format(acount_balance, transfer_balance)) quit() logger.log('USER-ACTION', "Requesting transfer of \u03C4{}, from coldkey: {} to destination: {}".format(transfer_balance.tao, self.wallet.coldkey.public_key, destination)) logger.log('USER-INFO', "Waiting for finalization...") result = self.subtensor.transfer( wallet = self.wallet, dest = destination, amount = transfer_balance, wait_for_finalization = True, timeout = bittensor.__blocktime__ * 5 ) if result: logger.log('USER-SUCCESS', "Transfer finalized with amount: \u03C4{} to destination: {} from coldkey.pub: {}".format(transfer_balance.tao, destination, self.wallet.coldkey.public_key)) else: logger.log('USER-CRITICAL', "Transfer failed")
def setUp(self): self.subtensor = bittensor.subtensor( network = 'nobunaga' ) self.wallet = bittensor.wallet() coldkey = Keypair.create_from_mnemonic(Keypair.generate_mnemonic()) self.wallet.set_coldkey(coldkey, encrypt=False, overwrite=True) self.wallet.set_coldkeypub(coldkey, encrypt=False, overwrite=True) self.wallet.set_hotkey(Keypair.create_from_mnemonic(Keypair.generate_mnemonic()), encrypt=False, overwrite=True) self.mock_neuron = self.subtensor._neuron_dict_to_namespace( dict({ "version":1, "ip":0, "port":0, "ip_type":0, "uid":1, "modality":0, "hotkey":'some_hotkey', "coldkey":'some_coldkey', "active":0, "last_update":0, "priority":0, "stake":1000000000000.0, "rank":0.0, "trust":0.0, "consensus":0.0, "incentive":0.0, "dividends":0.0, "emission":0.0, "bonds":[], "weights":[], "is_null":False }) ) self.neurons = self.subtensor.neurons() self.balance = Balance.from_tao(1000) assert True
def test_get_balance_no_balance(setup_chain): wallet = bittensor.wallet() subtensor = setup_subtensor(setup_chain) subtensor.register = MagicMock(return_value=True) subtensor.register(wallet=wallet) result = subtensor.get_balance(wallet.hotkey.ss58_address) assert result == Balance(0)
def get_balance(self, address: str) -> Balance: r""" Returns the token balance for the passed ss58_address address Args: address (Substrate address format, default = 42): ss58 chain address. Return: balance (bittensor.utils.balance.Balance): account balance """ result = self.substrate.get_runtime_state(module='System', storage_function='Account', params=[address], block_hash=None) balance_info = result.get('result') if not balance_info: return Balance(0) balance = balance_info['data']['free'] return Balance(balance)
def test_unstake_success(setup_chain): coldkeypair = Keypair.create_from_uri('//Alice') hotkey_pair = Keypair.create_from_mnemonic(Keypair.generate_mnemonic()) wallet = generate_wallet(coldkey_pair=coldkeypair, hotkey_pair=hotkey_pair) subtensor = connect(setup_chain) subtensor.is_connected() subscribe(subtensor, wallet) # Get the balance for the cold key, we use this for later comparison balance_pre = int(subtensor.get_balance(coldkeypair.public_key)) add_stake(subtensor, wallet, Balance(4000)) # Determine the cost of the add_stake transaction balance_post = int(subtensor.get_balance(coldkeypair.public_key)) transaction_fee_add_stake = balance_pre - balance_post - 4000 logger.error("Trans_fee add_stake: {}", transaction_fee_add_stake) # unstake incurs a transaction fee that is added to the block reward result = subtensor.unstake(amount=Balance(3000), wallet=wallet, hotkey_id=hotkey_pair.public_key, wait_for_finalization=True, timeout=30) assert result is True transaction_fee_unstake = balance_post - int( subtensor.get_balance(coldkeypair.public_key)) + 3000 logger.error("Trans_fee add_stake: {}", transaction_fee_unstake) assert int(transaction_fee_unstake) == TRANSACTION_FEE_UNSTAKE # At this point, the unstake transaction fee is in the transaction_fee_pool, and will make it into the block # reward the next block. However, in order to get this reward into the hotkey account of the neuron, # and emit needs to take place. This is why the expectation does not include the unstake transaction fee uid = subtensor.get_uid_for_pubkey(hotkey_pair.public_key) stake = subtensor.get_stake_for_uid(uid) expectation = 1000 + (3 * BLOCK_REWARD) + TRANSACTION_FEE_ADD_STAKE assert int(stake) == expectation
def test_get_balance_success(setup_chain): wallet = bittensor.wallet() hotkey_pair = Keypair.create_from_uri('//Bob') subtensor = setup_subtensor(setup_chain) #subtensor.register = MagicMock(return_value = True) subtensor.register(wallet=wallet) result = subtensor.get_balance(hotkey_pair.ss58_address) # Here 1040631877269 is the default account balance for Alice on substrate assert result == Balance(0)
def test_set_weights_success_transaction_fee(setup_chain): coldkeyA = Keypair.create_from_uri('//Alice') coldkeyB = Keypair.create_from_uri('//Bob') walletA = generate_wallet(coldkey_pair=coldkeyA) walletB = generate_wallet(coldkey_pair=coldkeyB) subtensorA = connect(setup_chain) subtensorB = connect(setup_chain) subtensorA.is_connected() subtensorB.is_connected() subscribe(subtensorA, walletA) # Sets a self weight of 1 subscribe(subtensorB, walletB) # Sets a self weight of 1 uidA = subtensorA.get_uid_for_pubkey(walletA.hotkey.public_key) uidB = subtensorB.get_uid_for_pubkey(walletB.hotkey.public_key) stake = 4000 transaction_fee = 14355 # Add stake to the hotkey account, so we can do tests on the transaction fees of the set_weights function # Keep in mind, this operation incurs transaction fees that are appended to the block_reward subtensorA.add_stake(wallet=walletA, amount=Balance(stake), hotkey_id=walletA.hotkey.public_key, wait_for_finalization=True, timeout=30) # At this point both neurons have equal stake, with self-weight set, so they receive each 50% of the block reward blocknr_pre = subtensorA.get_current_block() w_uids = [uidA, uidB] w_vals = [0, 1] subtensorA.set_weights(destinations=w_uids, values=w_vals, wait_for_finalization=True, timeout=4 * bittensor.__blocktime__, wallet=walletA) blocknr_post = subtensorA.get_current_block() blocks_passed = blocknr_post - blocknr_pre #logger.error(blocks_passed) # Check the stakes stakeA = subtensorA.get_stake_for_uid(uidA) expectation = int(stake + (0.99 * BLOCK_REWARD * 3) + 0.99 * TRANSACTION_FEE_ADD_STAKE) assert int(stakeA) == expectation # 1_485_018_355
async def add_stake( port:int, wallet:bittensor.wallet.Wallet, amount: Balance ): subtensor = connect( port ) await subtensor.is_connected() # Get the uid of the new neuron uid = await subtensor.get_uid_for_pubkey( wallet.hotkey.public_key ) assert uid is not None # Get the amount of stake, should be 0 result = await subtensor.get_stake_for_uid( uid ) assert int(result) == int(Balance(0)) # Add stake to new neuron await subtensor.add_stake( wallet = wallet, amount = amount, hotkey_id = hotkeypair.public_key )
def test_get_stake_for_uid___has_stake(setup_chain): hotkeypair = Keypair.create_from_mnemonic(Keypair.generate_mnemonic()) coldkeypair = Keypair.create_from_uri('//Alice') wallet = generate_wallet(coldkey_pair=coldkeypair, hotkey_pair=hotkeypair) subtensor = connect(setup_chain) subscribe(subtensor, wallet) uid = subtensor.get_uid_for_pubkey(hotkeypair.public_key) add_stake(subtensor, wallet, Balance(4000)) result = subtensor.get_stake_for_uid(uid) assert int(result) == 4000
def test_stake_failed( self ): class failed(): def __init__(self): self.is_success = False self.error_message = 'Mock' def process_events(self): return True self.subtensor.substrate.submit_extrinsic = MagicMock(return_value = failed()) self.subtensor.register = MagicMock(return_value = True) self.subtensor.neuron_for_pubkey = MagicMock(return_value = self.mock_neuron) self.subtensor.get_balance = MagicMock(return_value = Balance.from_tao(0)) fail= self.subtensor.add_stake(self.wallet, amount = 200, wait_for_inclusion = True ) assert fail == False
def test_transfer_success(setup_chain): coldkey_alice = Keypair.create_from_uri("//Alice") coldkey_bob = Keypair.create_from_uri("//Bob") subtensor = setup_subtensor(setup_chain) balance_alice_pre = subtensor.get_balance(coldkey_alice.ss58_address) balance_bob_pre = subtensor.get_balance(coldkey_bob.ss58_address) wallet_alice = generate_wallet(coldkey=coldkey_alice) result = subtensor.transfer(wallet=wallet_alice, dest=coldkey_bob.ss58_address, amount=100, wait_for_finalization=True) assert result == True balance_alice_post = subtensor.get_balance(coldkey_alice.ss58_address) balance_bob_post = subtensor.get_balance(coldkey_bob.ss58_address) # Bob should have its original balance + 100 that we transferred assert int(balance_bob_post) == int(balance_bob_pre) + int( Balance.from_tao(100))
def test_get_balance_no_balance(setup_chain): wallet = generate_wallet() subtensor = connect(setup_chain) subtensor.is_connected() result = subtensor.get_balance(wallet.hotkey.ss58_address) assert result == Balance(0)