def AddContract(self, contract): """ Add a contract to the database. Args: contract(neo.SmartContract.Contract): a Contract instance. """ super(UserWallet, self).AddContract(contract) try: db_contract = Contract.get(ScriptHash=contract.ScriptHash.ToBytes()) db_contract.delete_instance() except Exception as e: logger.info("contract does not exist yet") sh = bytes(contract.ScriptHash.ToArray()) address, created = Address.get_or_create(ScriptHash=sh) address.IsWatchOnly = False address.save() db_contract = Contract.create(RawData=contract.ToArray(), ScriptHash=contract.ScriptHash.ToBytes(), PublicKeyHash=contract.PublicKeyHash.ToBytes(), Address=address, Account=self.__dbaccount) logger.debug("Creating db contract %s " % db_contract) db_contract.save()
def DeleteAddress(self, script_hash): success, coins_toremove = super(UserWallet, self).DeleteAddress(script_hash) for coin in coins_toremove: try: c = Coin.get(TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex) c.delete_instance() except Exception as e: logger.error("Could not delete coin %s %s " % (coin, e)) todelete = bytes(script_hash.ToArray()) for c in Contract.select(): address = c.Address if address.ScriptHash == todelete: c.delete_instance() address.delete_instance() try: address = Address.get(ScriptHash=todelete) address.delete_instance() except Exception as e: pass return True, coins_toremove
def Addresses(self): result = [] try: for addr in Address.select(): result.append(addr.ToString()) except Exception as e: pass return result
def AddWatchOnly(self, script_hash): super(UserWallet, self).AddWatchOnly(script_hash) script_hash_bytes = bytes(script_hash.ToArray()) address = None try: address = Address.get(ScriptHash=script_hash_bytes) except Exception as e: # Address.DoesNotExist pass if address is None: address = Address.create(ScriptHash=script_hash_bytes, IsWatchOnly=True) address.save() return address else: raise Exception("Address already exists in wallet")
def OnCoinsChanged(self, added, changed, deleted): for coin in added: addr_hash = bytes(coin.Output.ScriptHash.Data) try: address = Address.get(ScriptHash=addr_hash) c = Coin(TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex, AssetId=bytes(coin.Output.AssetId.Data), Value=coin.Output.Value.value, ScriptHash=bytes(coin.Output.ScriptHash.Data), State=coin.State, Address=address) c.save() logger.debug("saved coin %s " % c) except Exception as e: logger.error("COULDN'T SAVE!!!! %s " % e) raise for coin in changed: for hold in self._holds: if hold.Reference == coin.Reference and coin.State & CoinState.Spent > 0: hold.IsComplete = True hold.save() try: c = Coin.get(TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex) c.State = coin.State c.save() except Exception as e: logger.error( "Coulndn't change coin %s %s (coin to change not found)" % (coin, e)) raise for coin in deleted: for hold in self._holds: if hold.Reference == coin.Reference: hold.IsComplete = True hold.save() try: c = Coin.get(TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex) c.delete_instance() except Exception as e: logger.error("could not delete coin %s %s " % (coin, e)) raise
def LoadWatchOnly(self): items = [] try: for addr in Address.select(): if addr.IsWatchOnly: watchOnly = UInt160(data=addr.ScriptHash) items.append(watchOnly) return items except Exception as e: logger.error("Could not load watch only: %s. You may need to migrate your wallet. Run 'wallet migrate'." % e) return []
def OnCoinsChanged(self, added, changed, deleted): for coin in added: addr_hash = bytes(coin.Output.ScriptHash.Data) try: address = Address.get(ScriptHash=addr_hash) c = Coin( TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex, AssetId=bytes(coin.Output.AssetId.Data), Value=coin.Output.Value.value, ScriptHash=bytes(coin.Output.ScriptHash.Data), State=coin.State, Address=address ) c.save() logger.debug("saved coin %s " % c) except Exception as e: logger.error("COULDN'T SAVE!!!! %s " % e) for coin in changed: for hold in self._holds: if hold.Reference == coin.Reference and coin.State & CoinState.Spent > 0: hold.IsComplete = True hold.save() try: c = Coin.get(TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex) c.State = coin.State c.save() except Exception as e: logger.error("Coulndn't change coin %s %s (coin to change not found)" % (coin, e)) for coin in deleted: for hold in self._holds: if hold.Reference == coin.Reference: hold.IsComplete = True hold.save() try: c = Coin.get(TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex) c.delete_instance() except Exception as e: logger.error("could not delete coin %s %s " % (coin, e))
def DeleteAddress(self, script_hash): success, coins_toremove = super(UserWallet, self).DeleteAddress(script_hash) for coin in coins_toremove: try: c = Coin.get(TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex) c.delete_instance() print("deleted coin!!!") except Exception as e: print("Couldnt delete coin %s %s " % (e, coin)) self.__log.debug("could not delete coin %s %s " % (coin, e)) address = Address.get(ScriptHash=bytes(script_hash.ToArray())) address.delete_instance() return True, coins_toremove
def __init__(self, public, is_mainnet): self._path = 'main123' if is_mainnet else 'test123' self.AddressVersion = 23 self._lock = RLock() self._indexedDB = Blockchain.Default() self.BuildDatabase() self._keys = {} self._contracts = self.LoadContracts() # for public in ['0294cd0a9e77f358f709e69d9375680b1eafe75373645192b5b251260f484577ea']: kp = OnlyPublicKeyPair(public) self._keys[kp.PublicKeyHash.ToBytes()] = kp contract = WalletContract.CreateSignatureContract(kp.PublicKey) if contract.ScriptHash.ToBytes() not in self._contracts.keys(): self._contracts[contract.ScriptHash.ToBytes()] = contract sh = bytes(contract.ScriptHash.ToArray()) address, created = Address.get_or_create(ScriptHash=sh) address.IsWatchOnly = False address.save() db_contract = Contract.create(RawData=contract.ToArray(), ScriptHash=contract.ScriptHash.ToBytes(), PublicKeyHash=contract.PublicKeyHash.ToBytes(), Address=address, Account=None ) self.LoadNamedAddresses() self._watch_only = self.LoadWatchOnly() self._tokens = self.LoadNEP5Tokens() self._coins = self.LoadCoins() self.initialize_holds() try: self._current_height = int(self.LoadStoredData('Height')) except: print('setting height to 0') self._current_height = 0 self.SaveStoredData('Height', self._current_height)
def OnCoinsChanged(self, added, changed, deleted): if len(added) > 0 or len(changed) > 0 or len(deleted) > 0: pass for coin in added: addr_hash = bytes(coin.Output.ScriptHash.Data) address = Address.get(ScriptHash=addr_hash) try: c = Coin(TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex, AssetId=bytes(coin.Output.AssetId.Data), Value=coin.Output.Value.value, ScriptHash=bytes(coin.Output.ScriptHash.Data), State=coin.State, Address=address) c.save() self.__log.debug("saved coin %s " % c) except Exception as e: print("COLUDNT SAVE!!!! %s " % e) for coin in changed: try: c = Coin.get(TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex) c.State = coin.State c.save() except Exception as e: print("Coulndnt change coin %s %s" % (coin, e)) self.__log.debug("coin to change not found! %s %s " % (coin, e)) for coin in deleted: try: c = Coin.get(TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex) c.delete_instance() except Exception as e: print("Couldnt delete coin %s %s " % (e, coin)) self.__log.debug("could not delete coin %s %s " % (coin, e))
def OnCoinsChanged(self, added, changed, deleted): for coin in added: addr_hash = bytes(coin.Output.ScriptHash.Data) try: address = Address.get(ScriptHash=addr_hash) c = Coin(TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex, AssetId=bytes(coin.Output.AssetId.Data), Value=coin.Output.Value.value, ScriptHash=bytes(coin.Output.ScriptHash.Data), State=coin.State, Address=address) c.save() except Exception as e: logger.error("[Path: %s ] Could not create coin: %s " % (self._path, e)) for coin in changed: try: c = Coin.get(TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex) c.State = coin.State c.save() except Exception as e: logger.error( "[Path: %s ] could not change coin %s %s (coin to change not found)" % (self._path, coin, e)) for coin in deleted: try: c = Coin.get(TxId=bytes(coin.Reference.PrevHash.Data), Index=coin.Reference.PrevIndex) c.delete_instance() except Exception as e: logger.error("[Path: %s] could not delete coin %s %s " % (self._path, coin, e))
def ToJson(self, verbose=False): assets = self.GetCoinAssets() tokens = list(self._tokens.values()) assets = assets + tokens if Blockchain.Default().Height == 0: percent_synced = 0 else: percent_synced = int(100 * self._current_height / Blockchain.Default().Height) jsn = {} jsn['path'] = self._path addresses = [] has_watch_addr = False for addr in Address.select(): logger.info("Script hash %s %s" % (addr.ScriptHash, type(addr.ScriptHash))) addr_str = Crypto.ToAddress(UInt160(data=addr.ScriptHash)) acct = Blockchain.Default().GetAccountState(addr_str) token_balances = self.TokenBalancesForAddress(addr_str) if acct: json = acct.ToJson() json['is_watch_only'] = addr.IsWatchOnly addresses.append(json) if token_balances: json['tokens'] = token_balances if addr.IsWatchOnly: has_watch_addr = True else: script_hash = binascii.hexlify(addr.ScriptHash) json = {'address': addr_str, 'script_hash': script_hash.decode('utf8'), 'tokens': token_balances} addresses.append(json) balances = [] watch_balances = [] for asset in assets: if type(asset) is UInt256: bc_asset = Blockchain.Default().GetAssetState(asset.ToBytes()) total = self.GetBalance(asset).value / Fixed8.D watch_total = self.GetBalance(asset, CoinState.WatchOnly).value / Fixed8.D balances.append("[%s]: %s " % (bc_asset.GetName(), total)) watch_balances.append("[%s]: %s " % (bc_asset.GetName(), watch_total)) elif type(asset) is WalletNEP5Token: balances.append("[%s]: %s " % (asset.symbol, self.GetBalance(asset))) watch_balances.append("[%s]: %s " % (asset.symbol, self.GetBalance(asset, True))) tokens = [] for t in self._tokens.values(): tokens.append(t.ToJson()) jsn['addresses'] = addresses jsn['height'] = self._current_height jsn['percent_synced'] = percent_synced jsn['synced_balances'] = balances if has_watch_addr: jsn['synced_watch_only_balances'] = watch_balances jsn['public_keys'] = self.PubKeys() jsn['tokens'] = tokens jsn['claims'] = { 'available': self.GetAvailableClaimTotal().ToString(), 'unavailable': self.GetUnavailableBonus().ToString() } alia = NamedAddress.select() if len(alia): na = {} for n in alia: na[n.Title] = n.ToString() jsn['named_addr'] = na if verbose: jsn['coins'] = [coin.ToJson() for coin in self.FindUnspentCoins()] jsn['transactions'] = [tx.ToJson() for tx in self.GetTransactions()] return jsn
def pretty_print(self, verbose=False): if Blockchain.Default().Height == 0: percent_synced = 0 else: percent_synced = int(100 * self._current_height / Blockchain.Default().Height) print(f"Path : {self._path}") print(f"Height : {self._current_height}") print(f"Sync status: {percent_synced}%") print(" ") # collect available public keys pubkeys = dict() for k in self.LoadKeyPairs().values(): pub = k.PublicKey.encode_point(True) for ct in self._contracts.values(): if ct.PublicKeyHash == k.PublicKeyHash: pubkeys.update({ct.Address: pub.decode('utf-8')}) # build data objects addresses = dict() for addr in Address.select(): addr_str = addr.ToString() addresses.update({ addr_str: { 'public_key': pubkeys.get(addr_str, "N/A"), 'script_hash': addr.ScriptHash, 'watchonly': addr.IsWatchOnly, 'assets': self._get_asset_balances(addr_str, addr.IsWatchOnly), 'tokens': self._get_token_balances(addr_str) } }) aliases = dict() alia = NamedAddress.select() for n in alia: aliases[n.Title] = n.ToString() # pretty print for address, data in addresses.items(): for title, addr in aliases.items(): if address == addr: print(f"Alias : {title}") addr_str = address + " (watch only)" if data[ 'watchonly'] else address print(f"Address : {addr_str}") if verbose: scripthash_le = binascii.hexlify(data['script_hash']).decode() scripthash_be = UInt160(data=data['script_hash']).To0xString() print(f"Public key : {data['public_key']}") print(f"Script hash: {data['script_hash']}") print(f" little endian: {scripthash_le}") print(f" big endian: {scripthash_be}") has_balances = False for asset_name, value in data['assets'].items(): if value > 0: symbol = f"[{asset_name}]" print(f"{symbol:<11}: {value}") has_balances = True for token_name, value in data['tokens'].items(): if value > 0: symbol = f"[{token_name}]" print(f"{symbol:<11}: {value}") has_balances = True if not has_balances: print(f"{'Balances':<11}: only zero") print(" ") print("Claims:") print(f" unlocked: {self.GetAvailableClaimTotal().ToString()}") print(f" locked : {self.GetUnavailableBonus().ToString()}")