def get_transfers(full_history, print_history=True): account_history_executing = True api = Iota(iota_node, seed) address_count = len(address_data) all_txn_hashes = [] saved_txn_hashes = [] new_txn_hashes = [] i = 0 while i < address_count: address = address_data[i]["address"] address_as_bytes = [bytes(address)] raw_transfers = api.find_transactions(addresses=address_as_bytes) transactions_to_check = raw_transfers["hashes"] for txn_hash in transactions_to_check: txn_hash = str(txn_hash) all_txn_hashes.append(txn_hash) i += 1 for txn_hash in transfers_data: txn_hash = str(txn_hash['transaction_hash']) saved_txn_hashes.append(txn_hash) for txn_hash in all_txn_hashes: if txn_hash not in saved_txn_hashes: new_txn_hashes.append(txn_hash) if len(new_txn_hashes) > 0: print("Retreaving and saving transfer data from " + str(len(new_txn_hashes)) + " transaction(s)!\n" "Please wait...\n") for txn_hash in new_txn_hashes: txn_hash_as_bytes = bytes(txn_hash) li_result = api.get_latest_inclusion([ txn_hash_as_bytes ]) # Needs to be integrated into new transactions as well is_confirmed = li_result['states'][txn_hash] print(li_result) gt_result = api.get_trytes([txn_hash_as_bytes]) trytes = str(gt_result['trytes'][0]) txn = Transaction.from_tryte_string(trytes) timestamp = str(txn.timestamp) tag = str(txn.tag) address = str(txn.address) message = "some message" # Placeholder untill message decoding is added value = str(txn.value) bundle = str(txn.bundle_hash) write_transfers_data(txn_hash, is_confirmed, timestamp, tag, address, message, value, bundle) if full_history: print_transaction_history(full_history, print_history) elif not full_history: print_transaction_history(full_history, print_history)
def test_wireup(self): """ Verify that the command is wired up correctly. (sync) The API method indeed calls the appropiate command. """ with patch('iota.commands.core.get_trytes.GetTrytesCommand.__call__', MagicMock(return_value=async_return( 'You found me!'))) as mocked_command: api = Iota(self.adapter) response = api.get_trytes('hashes') self.assertTrue(mocked_command.called) self.assertEqual(response, 'You found me!')
def get_transfers(self): """ Get transactions :return: """ api = Iota(current_app.config['IOTA_HOST'], self.seed) result = [] for a in self.addresses: t = api.find_transactions(addresses=[a.address]) for th in t['hashes']: gt = api.get_trytes([th]) txn = Transaction.from_tryte_string(gt['trytes'][0]) result.append(txn) return result
class Replay: def __init__(self, node, seed, bundle, replay_callback=None, depth=7, min_weight_magnitude=14): self.api = Iota(node, seed) self.depth = depth self.min_weight_magnitude = min_weight_magnitude if replay_callback: self.replay_callback = replay_callback self.replay(bundle) def fetch_tail_transaction(self, bundle_hash): ft_result = self.api.find_transactions(bundles=[bundle_hash]) transaction_hashes = ft_result['hashes'] gt_result = self.api.get_trytes(transaction_hashes) bundle = Bundle.from_tryte_strings(gt_result['trytes']) return bundle.tail_transaction.hash def replay(self, bundle): tail_transaction = self.fetch_tail_transaction(bundle) try: self.api.replay_bundle( transaction=tail_transaction, depth=self.depth, min_weight_magnitude=self.min_weight_magnitude) if callable(self.replay_callback): self.replay_callback( 'Successfully replayed your specified bundle!') except: if callable(self.replay_callback): self.replay_callback( 'Something went wrong while replaying your bundle! Please try again.' )
def waiting_for_payment(address_with_checksum, price_total): waiting = True while waiting == True: time.sleep(2) global node api = Iota(node) find_transaction = api.findTransactions( addresses=[bytes(address_with_checksum)]) try: hash_as_bytes = str(bytes(find_transaction["hashes"][0])) trytes_call = api.get_trytes([hash_as_bytes]) trytes = trytes_call['trytes'][0] txn = Transaction.from_tryte_string(trytes) if txn.value >= price_total: waiting = False except: print("Waiting..") os.system('cls' if os.name == 'nt' else 'clear') return True
def find_transaction_message(hash_txn): # Iota instance api = Iota(NODE_URL) message = "" list_txn = [] try: list_txn = api.get_trytes([hash_txn]) except BaseException: return "" trytes_txn = str(list_txn['trytes'][0]) txn = Transaction.from_tryte_string(trytes_txn) try: message = TryteString(txn.signature_message_fragment).decode() except BaseException: return "" return message
hashes = [] for txhash in transactions['hashes']: hashes.append(txhash) print(len(hashes), " hashes") # Divide the list of hashes into small batches chunks = [] if len(hashes) > n: chunks = [hashes[i:i + n] for i in range(0, len(hashes), n)] else: chunks.append(hashes) print(len(chunks), " batches") k = 0 for chunk in chunks: trytes = api.get_trytes(chunk)['trytes'] print(len(trytes), " messages") k += len(trytes) print(k, " messages saved") msgList = [] # Get the embedded message from the Signature Message Fragment for trytestring in trytes: tx = Transaction.from_tryte_string(trytestring) message = tx.signature_message_fragment msg = {} msg['hash'] = str(tx.hash) fields = message.decode().split(",") for f in range(len(fields)): msg["status"] = fields[f].strip("\n") msgList.append(msg)
class MyIOTA: def __init__(self, node, seed): self.node = node self.seed = seed self.api = False self._update = False self.transfers = [] self._debug = False self.wallet = self.get_filename() self.addr_dict = {} self.min_weight_magnitude = 14 self.api = Iota(self.node, self.seed) self.USED = True self.NOT_USED = False def Address(self, addr_string): return Address(addr_string) def get_addr_dict(self): return self.addr_dict def set_addr_dict(self, addr, value, used): self.addr_dict[addr] = (value, used) def s_addr(self, addr, n=3): s_addr = str(addr) l = len(s_addr) return s_addr[:n] + '...' + s_addr[l - n:] def get_filename(self): h = hashlib.sha256() h.update(self.seed) filename = h.hexdigest()[:20] + '.txt' return filename def init_wallet(self): filename = self.wallet # file exists if os.path.isfile(filename): filefd = open(filename, 'r+') self.debug( 'Wallet file {0} exists. Opening it...'.format(filename)) for line in filefd: line = line.rstrip('\n') addr, index, value, used = line.split(',') self.debug('reading from file: {0},{1},{2}'.format( self.s_addr(addr, 3), value, used)) used = used == 'True' addr = Address(addr, key_index=int(index), security_level=2) self.addr_dict[addr] = (int(index), int(value), used) filefd.close() else: filefd = open(filename, 'w') self.debug('Wallet file {0} doesnt exist. Creating it...'.format( filename)) filefd.close() def is_empty_wallet(self): return len(self.addr_dict) == 0 def get_fund_inputs(self, inputs): total_fund = 0 for addr in inputs: index, value, used = self.addr_dict[addr] # TODO: abs. is this right? total_fund += abs(value) return total_fund def write_updates(self): filefd = open(self.wallet, 'w') self.debug('Writing (updating) wallet...') for addr in self.addr_dict: v = self.addr_dict[addr] line = 'Writing: {0},{1},{2},{3}\n'.format(self.s_addr(addr), v[0], v[1], v[2]) self.debug(line) filefd.write('{0},{1},{2},{3}\n'.format(addr, v[0], v[1], v[2])) filefd.close() def update_wallet(self, input_fund, inputs, change_addr): copy_dict = self.addr_dict.copy() for addr in inputs: v = self.addr_dict[addr] #self.debug('Spending {0} from input {1}'.format(self.s_addr(addr), v)) # Negative fund and used address new_value = (v[0], -v[1], not v[2]) self.debug('Updating input address {0} to: {1}'.format( self.s_addr(addr), new_value)) self.addr_dict[addr] = new_value change_fund = self.get_fund_inputs(inputs) - input_fund v = self.addr_dict[change_addr] change_value = (v[0], change_fund, self.NOT_USED) self.debug('Updating change address {0} to: {1}'.format( self.s_addr(change_addr), change_value)) self.addr_dict[change_addr] = change_value self.write_updates() def enable_debug(self): self._debug = True def debug(self, msg): if self._debug: print '[+] Debug: ', msg def get_node_info(self): return self.api.get_node_info() def make_addr_list(self, start_index, n): self.iota_assert(start_index >= 0 and n > 0, 'must be positive numbers. N should be at least 1.') result = self.api.get_new_addresses(index=start_index, count=n) addresses = result['addresses'] for i in range(n): addr = addresses[i] value = self.get_addr_balance(addr) # TODO: Why always False self.addr_dict[addr] = (i, value, False) self.write_updates() def get_addr_balance(self, addr): # TODO: addr is a list with just one element result = self.api.get_balances([addr]) balance = result['balances'] return (balance[0]) def prepare_transfer(self, transfer_value, dest_addr, tag='DEFAULT', msg='DEFAULT'): # TODO: verify address (checksum) # TODO: use mi, gi, etc msg = TryteString.from_string(msg) txn = ProposedTransaction( address=Address(dest_addr), message=msg, tag=Tag(tag), value=transfer_value, ) return txn def find_transactions(self): addr_list = [] for e in self.addr_dict.items(): addr = e[0] addr_list.append(addr) return self.api.findTransactions(addresses=addr_list)['hashes'] def get_bundle(self, trans): return self.api.getBundles(transaction=trans) def get_latest_inclusion(self, addrl): return self.api.get_latest_inclusion(hashes=addrl) def get_total_fund(self): total_fund = 0 for addr in self.addr_dict.items(): # key and value from dict k, v = addr index, value, used = v #if not used: total_fund += value return total_fund def get_number_of_address(self): return len(self.addr_dict) def is_all_addr_used(self): for addr in self.addr_dict: for e in self.addr_dict.items(): addr, v = e index, value, used = v if used == False: return True def get_more_addr(self, n=10): start_index = self.get_number_of_address() self.debug('Getting more addresses...please wait...') self.make_addr_list(start_index, n) def send_transfer(self, input_fund, inputs, outputs, change_addr, savetofile=True): # TODO: How to send MANY transactions. self.debug('Sending {0} transactions, please wait...'.format( len(outputs))) self.api.send_transfer(inputs=inputs, transfers=outputs, depth=7, change_address=change_addr, min_weight_magnitude=self.min_weight_magnitude) self.debug('Sent.') if self.is_all_addr_used(): # We do an update to wallet file here. self.get_more_addr(n=10) if savetofile: self.update_wallet(input_fund, inputs, change_addr) def get_bundles(self, hasht): return self.api.get_bundles(hasht) def get_trytes(self, hashl): return self.api.get_trytes(hashl)['trytes'][0] def get_transaction_from_trytes(self, trytes): txn = Transaction.from_tryte_string(trytes) return txn def get_transaction_fields(self, txn): #confirmed = str(txn.is_confirmed) timestamp = str(txn.timestamp) address = str(txn.address) value = str(txn.value) message = str(txn.signature_message_fragment) #message = str(txn.message) tag = str(txn.tag) return (timestamp, address, value, tag, message) def get_info_transactions(self, transactions_hashes): txn_tuples = [] for h in transactions_hashes: trytes = self.get_trytes([h]) txn = self.get_transaction_from_trytes(trytes) # Get confirmed flag li_result = self.get_latest_inclusion([bytes(h)]) confirmed_t = li_result['states'][h] (_, addr_t, value_t, tag_t, msg_t) = self.get_transaction_fields(txn) txn_tuples.append((confirmed_t, addr_t, value_t, tag_t, msg_t)) return txn_tuples def get_any_valid_addr(self): #TODO: verify #return self.addr_dict.keys()[0] for e in self.addr_dict.items(): addr, v = e index, value, used = v if not used: return addr return None def get_inputs(self, fund): # TODO: Zero fund fund_sum = 0 addr_list = [] change_addr = None # Zero fund transactions. We return any addr and any change_addr if fund == 0: # TODO: What if it conflicts with one another? addr_list.append(self.get_any_valid_addr()) change_addr = self.get_any_valid_addr() return (addr_list, change_addr) for e in self.addr_dict.items(): addr, v = e index, value, used = v if fund_sum < fund: #if value > 0 and not used: if value > 0 and used == self.NOT_USED: fund_sum += value self.debug( 'Found request: {0}. Found address {1} with fund {2}.'. format(fund, self.s_addr(addr), value)) addr_list.append(addr) for e in self.addr_dict.items(): addr, v = e index, value, used = v if used == self.NOT_USED and addr not in addr_list: change_addr = addr self.debug('Using {0} as change addr.'.format( self.s_addr(addr))) break return (addr_list, change_addr) #else: # # TODO # self.iota_assert(True, 'No change addr available.') def iota_assert(self, condition, msg): if not condition: print 'Error: ', msg sys.exit(-1)
class IotaClient(object): """Python IOTA client wrapper""" def __init__(self, seed, provider, depth=5, min_weight_magnitude=14): self._api = Iota(provider, seed) self._depth = depth self._min_weight_magnitude = min_weight_magnitude self.address = self._get_address() @staticmethod def _compose_transaction(address, msg, tag, val): txn = \ ProposedTransaction( address=Address(address), message=TryteString.from_unicode(msg), tag=Tag(tag), value=val ) return txn def _get_address(self): address = self._api.get_new_addresses(0, 1)['addresses'][0] return str(address) def get_transactions_from_address(self, address): """ Gets transaction object from address sorted on timestamp (from latest to earliest). :param address: Address to fetch transaction from """ transactions = self._api.find_transactions(addresses=[address]) transaction_hashes = transactions['hashes'] if not transaction_hashes: raise ValueError("No transactions on address") trytes = self._api.get_trytes(transaction_hashes)['trytes'] trytes_and_hashes = list(zip(trytes, transaction_hashes)) transactions = list( map(lambda pair: Transaction.from_tryte_string(pair[0], pair[1]), trytes_and_hashes)) sorted_transactions = sorted(transactions, key=lambda t: t.timestamp, reverse=True) return sorted_transactions def get_messages_from_address(self, address): """ Gets messages (sorted by timestamp). Returns a dict with 'json_message' and 'timestamp keys' :param address: Address to fetch messages from """ sorted_transactions = self.get_transactions_from_address(address) messages = list( map( lambda t: { 'json_message': json.loads(Fragment.as_string(t.signature_message_fragment) ), 'timestamp': t.timestamp }, sorted_transactions)) return messages @staticmethod def get_message(transaction): message = transaction['signature_message_fragment'].decode() json_message = json.loads(message) return json_message def send_transaction(self, address, msg, tag, val): txn = self._compose_transaction(Address(address), msg, tag, val) mwm = self._min_weight_magnitude depth = self._depth self._api.send_transfer(depth, [txn], None, None, mwm)
from datetime import datetime from iota import Address, Iota, Transaction with open("tangle/config/address_tan.conf") as in_file: # read as string # strip any carriage return characters # and encode as bytes() ADDRESS = in_file.read().rstrip("\n").encode() # 0. Where is data stored? receiver = Address(ADDRESS) # 1. Connect to public node api = Iota("https://durian.iotasalad.org:14265") # 2. Retrieve all transactions txs = api.find_transactions(addresses=[receiver]) # 3. Iterate over transactions, decode and print for tx_hash in txs["hashes"]: tx_hash_b = bytes(tx_hash) tx_data_trytes = api.get_trytes([tx_hash_b]) tryte_str = str(tx_data_trytes["trytes"][0]) tx = Transaction.from_tryte_string(tryte_str) timestamp = datetime.fromtimestamp(tx.timestamp) tx_data = str(tx.signature_message_fragment.decode()) print("{ts}: {tx}".format(ts=timestamp, tx=tx_data))
class IotaCache(object): def __init__(self, uri=None, seed=None): if not uri: self.uri = "http://localhost:14700" else: self.uri = uri if not seed: self.seed = 'EBZYNR9YVFIOAZUPQOLRZXPPPIKRCJ9EJKVCXMYVLMNOCCOPYPJKCWUZNLJZZZZWTMVQUXZFYLVLZXJ9Q' else: self.seed = seed self.api = Iota(self.uri, self.seed, testnet=True) self.mwm = 1 self.depth = 15 def cache_txn_in_tangle_sdk(self, ipfs_addr, tag): api_response = self.api.get_new_addresses() addy = api_response['addresses'][0] address = binary_type(addy).decode('ascii') result = self.api.send_transfer( depth=self.depth, transfers=[ ProposedTransaction( address=Address(address), value=0, tag=Tag(tag), message=TryteString.from_string(ipfs_addr), ), ], min_weight_magnitude=self.mwm, ) return result def cache_txn_in_tangle_simple(self, data, tag): address = "JVSVAFSXWHUIZPFDLORNDMASGNXWFGZFMXGLCJQGFWFEZWWOA9KYSPHCLZHFBCOHMNCCBAGNACPIGHVYX" txns = self.api.get_transactions_to_approve(self.depth) tr = self.api.get_trytes([txns[u'branchTransaction']]) txn = Transaction.from_tryte_string(tr[u'trytes'][0], txns[u'branchTransaction']) txn.trunk_transaction_hash = txns[u'trunkTransaction'] txn.branch_transaction_hash = txns[u'branchTransaction'] txn.tag = Tag(TryteString.from_string(tag)) txn.signature_message_fragment = Fragment(TryteString.from_bytes(data)) attach_trytes = attachToTangle(self.uri, txns[u'trunkTransaction'].__str__(), txns[u'branchTransaction'].__str__(), 1, txn.as_tryte_string().__str__()) res = self.api.broadcast_and_store(attach_trytes[u'trytes']) return res def cache_txn_in_tangle_message(self, data, tag): #address = "JVSVAFSXWHUIZPFDLORNDMASGNXWFGZFMXGLCJQGFWFEZWWOA9KYSPHCLZHFBCOHMNCCBAGNACPIGHVYX" address = "14dD6ygPi5WXdwwBTt1FBZK3aD8uDem1FY" res = storeMessage(self.uri, address, data, tag) return res def get_balance(self, coin_type, account): address = "JVSVAFSXWHUIZPFDLORNDMASGNXWFGZFMXGLCJQGFWFEZWWOA9KYSPHCLZHFBCOHMNCCBAGNACPIGHVYX" res = getBalance(self.uri, address, coin_type, account) return res def get_approved_txns(self, tag): ret = [] transactions = self.api.find_transactions(None, None, [tag], None) if len(transactions['hashes']) == 0: return ret tips = self.api.get_tips() states = self.api.get_inclusion_states(transactions['hashes'], tips['hashes']) i = 0 for txn in transactions['hashes']: if states['states'][i] is True: ret.append(txn) return ret def get_non_consumed_txns(self, tag): ret = [] txn_hashes_all = self.get_approved_txns(tag) if len(txn_hashes_all) == 0: return ret txn_trytes_all = self.api.get_trytes(txn_hashes_all) consumedSet = [] txn_hashes_consumed = self.api.find_transactions(None, None, [tag+b"CONSUMED"], None) if len(txn_hashes_consumed['hashes']) != 0: txn_trytes_consumed = self.api.get_trytes(txn_hashes_consumed['hashes']) i=0 for txnTrytes in txn_trytes_consumed['trytes']: txn = Transaction.from_tryte_string(txnTrytes, txn_hashes_consumed['hashes'][i]) i+=1 consumedSet.append(txn.signature_message_fragment) i=0 for txnTrytes in txn_trytes_all['trytes']: txn = Transaction.from_tryte_string(txnTrytes, txn_hashes_all[i]) i+=1 if txn.signature_message_fragment not in consumedSet: msgTryte = txn.signature_message_fragment.decode() ret.append(msgTryte) return ret def set_txn_as_synced(self, ipfs_addr, tag): result = self.cache_txn_in_tangle_sdk(ipfs_addr, tag+b"CONSUMED") return result def add_neighbors(self, uris): res = addNeighbors(self.uri, uris) return res def get_block_content(self, hashes): res = getBlockContent(self.uri, hashes) return res def get_dag(self, dag_type): res = getDAG(self.uri, dag_type) return res def get_utxo(self, dag_type): res = getUTXO(self.uri, dag_type) return res def get_total_order(self): res = getTotalOrder(self.uri) return res
class IotaCache(object): def __init__(self, uri=None, seed=None): if not uri: self.uri = "http://localhost:14700" else: self.uri = uri if not seed: self.seed = 'EBZYNR9YVFIOAZUPQOLRZXPPPIKRCJ9EJKVCXMYVLMNOCCOPYPJKCWUZNLJZZZZWTMVQUXZFYLVLZXJ9Q' else: self.seed = seed self.api = Iota(self.uri, self.seed) def cache_txn_in_tangle(self, ipfs_addr, tag): api_response = self.api.get_new_addresses() addy = api_response['addresses'][0] address = binary_type(addy).decode('ascii') result = self.api.send_transfer( depth=3, transfers=[ ProposedTransaction( address=Address(address), value=0, tag=Tag(tag), message=TryteString.from_string(ipfs_addr), ), ], ) return result def get_approved_txns(self, tag): ret = [] transactions = self.api.find_transactions(None, None, [tag], None) if len(transactions['hashes']) == 0: return ret tips = self.api.get_tips() states = self.api.get_inclusion_states(transactions['hashes'], tips['hashes']) i = 0 for txn in transactions['hashes']: if states['states'][i] is True: ret.append(txn) return ret def get_non_consumed_txns(self, tag): txn_hashes_all = self.get_approved_txns(tag) txn_trytes_all = self.api.get_trytes(txn_hashes_all) txn_hashes_consumed = self.api.find_transactions( None, None, [tag + b"CONSUMED"], None) txn_trytes_consumed = self.api.get_trytes( txn_hashes_consumed['hashes']) consumedSet = [] ret = [] for txnTrytes in txn_trytes_consumed['trytes']: txn = Transaction.from_tryte_string(txnTrytes) consumedSet.append(txn.signature_message_fragment) for txnTrytes in txn_trytes_all['trytes']: txn = Transaction.from_tryte_string(txnTrytes) if txn.signature_message_fragment not in consumedSet: msgTryte = txn.signature_message_fragment.decode() ret.append(msgTryte) return ret def set_txn_as_synced(self, ipfs_addr, tag): result = self.cache_txn_in_tangle(ipfs_addr, tag + b"CONSUMED") return result
class TangleConnector: def __init__(self, url='https://nutzdoch.einfachiota.de', seed="TESTSEED9"): self.iri_url = url self.iota_api = Iota(url, seed) def get_node(self) -> dict: """ Get IRI node info """ try: res = self.iota_api.get_node_info() except Exception as e: logging.warning("Failed to IRI node info for " + self.iri_url, e) res = None return res def get_tips(self) -> dict: """ Get all unreferenced transactions """ try: res = self.iota_api.get_tips() except Exception as e: logging.warning("Failed to get tips", e) res = None return res def get_hashes_from_addr(self, address: Address) -> List[TransactionHash]: """ Get all tx from address """ try: response = self.iota_api.find_transactions(addresses=[address]) hashes = response['hashes'] except Exception as e: logging.warning( "Failed to get all tx from address " + address.__str__(), e) hashes = None return hashes def get_trytes_from_hashes( self, hashes: List[TransactionHash]) -> List[TryteString]: """ Get tryte signature fragments from hashes """ try: response = self.iota_api.get_trytes(hashes) if response['trytes']: trytes = [tryte[0:2187] for tryte in response['trytes']] except Exception: #logging.warning("Failed to get all signature fragments") trytes = None return trytes def get_all_trytes_from_address( self, address: Address) -> Dict[TransactionHash, TryteString]: """ Get all trytes from address """ hashes = self.get_hashes_from_addr(address) trytes = self.get_trytes_from_hashes(hashes) if hashes and trytes: result = dict(zip(hashes, trytes)) else: result = None return result @staticmethod def get_json_from_tryte(tryte: TryteString) -> dict: try: str_from_tryte = tryte.as_string() dict_from_tryte = json.loads(str_from_tryte) except Exception as e: logging.error("Failed to convet trytes to JSON", e) dict_from_tryte = None return dict_from_tryte def send_msg_to_addr(self, address: Address, msg: str, tag: str) -> dict: """ Sends msg on Tangle to address with a tag """ try: response = self.iota_api.send_transfer( depth=5, transfers=[ ProposedTransaction(address=address, value=0, tag=Tag(tag), message=TryteString.from_string(msg)) ]) except Exception as e: logging.warning( "Message '" + msg + "' has failed to be stored in " + address.__str__(), e) response = None return response
class TangleConnector: def __init__(self, url='https://perma.iota.partners:443', seed="TESTSEED9"): self.iri_url = url self.iota_api = Iota(url, seed) def get_node(self) -> Dict: """ Get IRI node info """ try: res = self.iota_api.get_node_info() except BadApiResponse as e: logger.warning("Failed to IRI node info for " + self.iri_url, e) res = None return res def get_tips(self) -> Dict: """ Get all unreferenced transactions """ try: res = self.iota_api.get_tips() except BadApiResponse as e: logger.warning("Failed to get tips", e) res = None return res def get_hashes_from_addr(self, address: Address) -> List[TransactionHash]: """ Get all tx from address """ try: response = self.iota_api.find_transactions(addresses=[address]) hashes = response['hashes'] except (BadApiResponse, KeyError) as e: logger.warning( "Failed to get all tx from address " + address.__str__(), e) hashes = None return hashes def get_trytes_from_hashes( self, hashes: List[TransactionHash]) -> List[TryteString]: """ Get tryte signature fragments from hashes """ try: response = self.iota_api.get_trytes(hashes) trytes = [tryte[0:2187] for tryte in response['trytes']] except (BadApiResponse, KeyError) as e: logger.warning("Failed to get all signature fragments", e) trytes = None return trytes def get_all_trytes_from_address( self, address: Address) -> Dict[TransactionHash, TryteString]: """ Get all trytes from address """ hashes = self.get_hashes_from_addr(address) trytes = self.get_trytes_from_hashes(hashes) if hashes and trytes: result = dict(zip(hashes, trytes)) else: result = None return result @staticmethod def get_json_from_tryte(tryte: TryteString) -> Dict: try: str_from_tryte = tryte.as_string() dict_from_tryte = json.loads(str_from_tryte) except ValueError as e: logger.error("Failed to convet trytes to JSON", e) dict_from_tryte = None return dict_from_tryte def send_msg_to_addr(self, address: Address, msg: str, tag: str) -> Dict: """ Sends msg on Tangle to address with a tag """ try: response = self.iota_api.send_transfer( depth=2, transfers=[ ProposedTransaction(address=address, value=0, tag=Tag(tag), message=TryteString.from_string(msg)) ]) except BadApiResponse as e: logger.warning( "Message '" + msg + "' has failed to be stored in " + address.__str__(), e) response = None return response def get_bundles_from_addr(self, address: Address) -> List[Dict]: ''' Retrive all bundles sent to this address from IRI # requres IRI 1.6+ (or it seems so) ''' hashes = self.get_hashes_from_addr(address) bundles = [] if hashes: for tx in hashes: try: # have to loop through all txs, if tx is not 'tail' of a bundle then get_bundles() throws error bundle = self.iota_api.get_bundles(tx) except BadApiResponse: bundle = None if bundle: bundles.append(bundle) return bundles def get_messages_from_bundles(self, bundles: List) -> Dict: """ Loop through list of bundles and get string per bundle # requres IRI 1.6+ (or it seems so) """ output_msgs = {} for bundle in bundles: tx_list = bundle['bundles'][0].as_json_compatible() msg = '' for tx in tx_list: # if its a bundle with iotas, just get text from first tx in bundle, the rest are signatures if tx['current_index'] == 0 and tx['value'] > 0: msg = tx['signature_message_fragment'].as_string() break # if its a bundle without iota value, then consequently get all message fields and join strings if tx['value'] == 0: msg = msg + tx['signature_message_fragment'].as_string() bundle_hash = tx_list[0]['bundle_hash'].__str__() addr = tx_list[0]['address'].__str__() timestamp = tx_list[0]['timestamp'] value = tx_list[0]['value'] output_msgs[bundle_hash] = { 'msg': msg, 'address': addr, 'timestamp': timestamp, 'value': value } return output_msgs def get_all_msg_from_addr_by_bundle(self, address: Address) -> Dict: ''' Get dict of all msg with timestamps from address by bundle hash as key # requres IRI 1.6+ (or it seems so) ''' bundles = self.get_bundles_from_addr(address) hashes_and_msgs = self.get_messages_from_bundles(bundles) return hashes_and_msgs
class Verifier: def __init__(self, id, iota_host, seed, push): self._id = id self._iota_obj = Iota(iota_host, seed) self._conn = None self._push_data = push self._initial_setup() def _initial_setup(self): _create_table_reqd = not os.path.exists(DB_FILE) self._conn = sqlite3.connect(DB_FILE) c = self._conn.cursor() if _create_table_reqd: cmd_ = "CREATE TABLE {t_name} (msg_id INTEGER PRIMARY KEY, timestamp TEXT, " \ "item_name TEXT, item_value TEXT)".format(t_name=TABLE_NAME) c.execute(cmd_) c.execute("PRAGMA TABLE_INFO ({t_name})".format(t_name=TABLE_NAME)) column_names = [t[1] for t in c.fetchall()] if self._id not in column_names: c.execute("ALTER TABLE {t_name} ADD COLUMN '{c_name}' TEXT DEFAULT 'False'"\ .format(t_name=TABLE_NAME, c_name=self._id)) self._conn.commit() def fetch_data_from_tangle(self, msg_id): txns = self._iota_obj.find_transactions( tags=[Tag(TryteString.from_unicode(msg_id))]) _trytes = self._iota_obj.get_trytes(txns['hashes']).get('trytes', []) _values = [] for _t in _trytes: _txn = Transaction.from_tryte_string(_t) _value = json.loads(_txn.signature_message_fragment.decode()) _msg_value = _value.get('data', None) _msg_topic = _value.get('topic', None) _time = _txn.timestamp print('Message ID : %s, Message Topic: %s, Value found : %s' \ %(msg_id, _msg_topic, _msg_value,)) if self._push_data: # TBD : Push back to MQTT pass _tmp = (_msg_topic, _msg_value, _time) _values.append(_tmp) return _values def verification(self, topic, value): print('Please overload this method in your class ... ') return 'False' def save_to_db(self, msg_id, timestamp, item_name, item_value, verification_ans): c = self._conn.cursor() _msg_id = int(msg_id) _time_val = str(timestamp) try: _time_val = time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime(timestamp)) except: pass try: _cmd = "INSERT INTO {t_name} (msg_id, timestamp, item_name, item_value, {v_name}) "\ "VALUES ('{m_id}', '{t}', '{i_name}', '{i_val}', '{v_val}') "\ .format(t_name=TABLE_NAME, v_name=self._id, m_id=_msg_id, t=_time_val, i_name=item_name, i_val=item_value, v_val=verification_ans) c.execute(_cmd) except sqlite3.IntegrityError: # Row was already present, just update it with our verification answer c.execute("UPDATE {t_name} SET {c_name}='{c_val}' WHERE msg_id={m_id}"\ .format(t_name=TABLE_NAME, c_name=self._id, c_val=verification_ans, m_id=_msg_id)) self._conn.commit() def run(self, msg_id): values = self.fetch_data_from_tangle(msg_id) # For each msg_id there should be only one value if len(values) == 0: return elif len(values) > 1: raise Exception value = values[0] msg_topic = value[0] msg_value = value[1] msg_time = value[2] verification_ans = self.verification(msg_topic, msg_value) self.save_to_db(msg_id=msg_id, timestamp=msg_time, item_name=msg_topic, item_value=msg_value, verification_ans=verification_ans) def __del__(self): self._conn.close()
logging.info( f'hash: {curr_hash}, address: {address[i]}, tag: {tag}, message: {message[i]}' ) # Get raw transaction trytes txn_trytes = [] txn_hashes = [] txn_tags = [] for i in range(sent_transaction_number): txn_trytes.append( txn_array[i]['bundle'].tail_transaction.as_tryte_string()) txn_hashes.append(txn_array[i]['bundle'].tail_transaction.hash) txn_tags.append(txn_array[i]['bundle'].tail_transaction.tag) #==============Fetch transaction==============# get_trytes_res = api.get_trytes(txn_hashes) if get_trytes_res == None: logging.error("None responded transactions") exit(1) else: length = len(get_trytes_res['trytes']) for i in range(length): txn = Transaction.from_tryte_string(get_trytes_res['trytes'][i]) if txn.tag != tag: logging.error(f"Error expect: {tag}\nactual: {txn.tag[0:27]}") exit(1) if not (address[i] in txn.address): logging.error( f"address Error expect: {address[i]}\nactual: {txn.address[0:81]}" )
'interruptAttachingToTangle', LOCAL_NODE)) bundle_hash = input('Paste bundle hash: ') """ API.replay_bundle does not accept a bundle hash as argument. You have to pass the transaction hash with a currentIndex of 0 (= the first transaction or "tail transaction" of a bundle). That's why we have to get the transaction hashes of the bundle with API.find_transactions. Then we have to find out which of the returned transactions has a currentIndex of 0. """ print('Fetching transaction hashes...') transaction_hashes = API.find_transactions(bundles=[bundle_hash])['hashes'] print('Received transaction hashes.') print('Fetching transaction trytes...') bundle_trytes = API.get_trytes(transaction_hashes)['trytes'] print('Received transaction trytes.') from iota import Transaction for transaction_trytes in bundle_trytes: transaction = Transaction.from_tryte_string(transaction_trytes) if transaction.is_tail: print('Reattaching...') API.replay_bundle(transaction.hash, 3) print('Reattached') break
class IOTAWrapper: def __init__(self, seed=IOTA_SEED, node_address=IOTA_PROVIDER): self.api = Iota(node_address, seed) def get_traffic_status_within(self, radius_in_km, latitude, longitude): """ Get traffic status within a radius from longitude and latitude""" traffics = [] if latitude is None or longitude is None: return [] transactions = self._find_transaction() if transactions is not None and len(transactions) > 0: for tx in transactions: if is_within_certain_radius(tx, float(latitude), float(longitude), radius_in_km): traffics.append(tx) return traffics def broadcast_traffic_status(self, latitude, longitude, traffic_status, tag=MTRAFFIC_REG_TAG, depth=4, min_weight_magnitude=None): logger.info( "Broadcast traffic status at lat:{}, lon:{}, status:{}".format( latitude, longitude, traffic_status)) message = { "lat": latitude, "lon": longitude, "status": traffic_status, "timestamp": get_current_timestamp() } try: transfers = [ # All hail the glory of IOTA and their dummy transactions for tag retrieval. Without multiple # transaction, Tangle doesn't seem to pick up our Tag and completely change the value of Tag ProposedTransaction( # This address is wholeheartedly irrelevant address=Address( "FNAZ9SXUWMPPVHKIWMZWZXSFLPURWIFTUEQCMKGJAKODCMOGCLEAQQQH9BKNZUIFKLOPKRVHDJMBTBFYK" ), value=0), ProposedTransaction( address=Address( "FNAZ9SXUWMPPVHKIWMZWZXSFLPURWIFTUEQCMKGJAKODCMOGCLEAQQQH9BKNZUIFKLOPKRVHDJMBTBFYK" ), value=0, tag=get_tags(tag), message=TryteString.from_string(json.dumps(message)), ) ] response = self.api.send_transfer( depth=depth, transfers=transfers, min_weight_magnitude= min_weight_magnitude, # if None, the api will use default number for main-net ) except ConnectionError as e: logger.exception("Connection error: {e}".format(e=e)) except BadApiResponse as e: logger.exception("Bad Api Response: {e}".format(e=e)) except: logger.exception("Bad coding") else: bundle = Bundle(response['bundle']) print("Bundle Hash: {}\nFrom Address: {}\nTag:".format( bundle.hash, bundle.transactions[0].address, bundle.transactions[0].tag)) return response def _find_transaction(self, tag=MTRAFFIC_REG_TAG): try: response = self.api.find_transactions(tags=[get_tags(tag)]) except ConnectionError as e: logger.exception("Connection error: {e}".format(e=e)) except BadApiResponse as e: logger.exception("Bad Api Response: {e}".format(e=e)) else: if len(response["hashes"]) < 1: return [] trytes = self.api.get_trytes(response["hashes"]) transactions = [] for trytestring in trytes["trytes"]: tx = Transaction.from_tryte_string(trytestring) transactions.append(tx) return [ json.loads(tx.signature_message_fragment.as_string()) for tx in transactions ]
result = api.find_transactions(addresses=address) # Create a list of transaction hashes myhashes = result['hashes'] # Print wait message print("Please wait while retrieving cleaning records from the tangle...") # Loop trough all transaction hashes for txn_hash in myhashes: # Convert to bytes txn_hash_as_bytes = bytes(txn_hash) # Get the raw transaction data (trytes) of transaction gt_result = api.get_trytes([txn_hash_as_bytes]) # Convert to string trytes = str(gt_result['trytes'][0]) # Get transaction object txn = Transaction.from_tryte_string(trytes) # Get transaction timestamp timestamp = txn.timestamp # Convert timestamp to datetime clean_time = datetime.datetime.fromtimestamp(timestamp).strftime( '%Y-%m-%d %H:%M:%S') # Get transaction message as string
import pprint api = Iota('https://nodes.devnet.iota.org:443') address = 'TOKLOARHKXQCVPPVVIPIJGLUTLTKFHYGMBBLOXJFYGSARLOTYFFSDZNYCOBOCNPGRMJWZCQBNOROUCE9G' transactions = api.find_transactions(addresses=[address,]) # We found all transactions on this address, now we need to put all hashes # in a iterable to send it to the get_trytes function hashes = [] for txhash in transactions['hashes']: hashes.append(txhash) # Get Trytes accepts multiple Transaction Hashes trytes = api.get_trytes(hashes)['trytes'] # get_trytes returns us a list fo raw trytes, so we need to convert them # into transaction objects first for trytestring in trytes: tx = Transaction.from_tryte_string(trytestring) print('\n\nTransaction %s (tag %s):' % (tx.hash, tx.tag)) # To see what's avaialble in this object uncomment the next line # pprint.pprint(tx.as_json_compatible()) # Get the embedded message from the Signature Mesage Fragment message = tx.signature_message_fragment try: print(message.decode('UTF-8')) except:
def get_transfers(self, full_history, print_history=False): """ Gets all associated transactions from the saved addresses and saves the transaction data in the account file :param full_history: :param print_history: :return: """ self._account_history_executing = True api = Iota(self.iota_node, self._seed) address_count = len(self._data['account_data'][0]['address_data']) my_all_txn_hashes = {} all_txn_hashes = [] saved_txn_hashes = [] new_txn_hashes = [] i = 0 while i < address_count: address = self._data['account_data'][0]['address_data'][i][ "address"] address_as_bytes = [address] raw_transfers = api.find_transactions(addresses=address_as_bytes) transactions_to_check = raw_transfers["hashes"] for txn_hash in transactions_to_check: str_txn_hash = str(txn_hash) all_txn_hashes.append(str_txn_hash) my_all_txn_hashes[str_txn_hash] = txn_hash i += 1 for txn_hash in self._data['account_data'][0]['transfers_data']: txn_hash = str(txn_hash['transaction_hash']) saved_txn_hashes.append(txn_hash) for th in my_all_txn_hashes: if th not in saved_txn_hashes: new_txn_hashes.append(my_all_txn_hashes[th]) if len(new_txn_hashes) > 0: self._logger.info("Retrieving and saving transfer data from " + str(len(new_txn_hashes)) + " transaction(s)! Please wait...") for txn_hash in new_txn_hashes: li_result = api.get_latest_inclusion([ txn_hash ]) # Needs to be integrated into new transactions as well is_confirmed = li_result['states'][txn_hash] gt_result = api.get_trytes([txn_hash]) trytes = str(gt_result['trytes'][0]) txn = Transaction.from_tryte_string(trytes) timestamp = str(txn.timestamp) tag = str(txn.tag) address = str(txn.address) message = "some message" # Placeholder untill message decoding is added value = str(txn.value) bundle = str(txn.bundle_hash) self._write_transfers_data(str(txn_hash), is_confirmed, timestamp, tag, address, message, value, bundle) self.on_new_transaction_received(txn, is_confirmed) if print_history: if full_history: self.print_full_account_info() elif not full_history: self.print_standard_account_info() self._account_history_executing = False