class StrictIota(with_metaclass(ApiMeta)): """ API to send HTTP requests for communicating with an IOTA node. This implementation only exposes the "core" API methods. For a more feature-complete implementation, use :py:class:`Iota` instead. References: - https://iota.readme.io/docs/getting-started """ commands = discover_commands('iota.commands.core') def __init__(self, adapter, testnet=False): # type: (AdapterSpec, bool) -> None """ :param adapter: URI string or BaseAdapter instance. :param testnet: Whether to use testnet settings for this instance. """ super(StrictIota, self).__init__() if not isinstance(adapter, BaseAdapter): adapter = resolve_adapter(adapter) self.adapter = adapter # type: BaseAdapter self.testnet = testnet def __getattr__(self, command): # type: (Text) -> BaseCommand """ Creates a pre-configured command instance. This method will only return commands supported by the API class. If you want to execute an arbitrary API command, use :py:meth:`create_command`. :param command: The name of the command to create. References: - https://iota.readme.io/docs/making-requests """ # Fix an error when invoking :py:func:`help`. # https://github.com/iotaledger/iota.lib.py/issues/41 if command == '__name__': # noinspection PyTypeChecker return None try: command_class = self.commands[command] except KeyError: raise InvalidCommand( '{cls} does not support {command!r} command.'.format( cls=type(self).__name__, command=command, ), ) return command_class(self.adapter) def create_command(self, command): # type: (Text) -> CustomCommand """ Creates a pre-configured CustomCommand instance. This method is useful for invoking undocumented or experimental methods, or if you just want to troll your node for awhile. :param command: The name of the command to create. """ return CustomCommand(self.adapter, command) @property def default_min_weight_magnitude(self): # type: () -> int """ Returns the default ``min_weight_magnitude`` value to use for API requests. """ return 9 if self.testnet else 14 def add_neighbors(self, uris): # type: (Iterable[Text]) -> dict """ Add one or more neighbors to the node. Lasts until the node is restarted. :param uris: Use format ``udp://<ip address>:<port>``. Example: ``add_neighbors(['udp://example.com:14265'])`` References: - https://iota.readme.io/docs/addneighors """ return core.AddNeighborsCommand(self.adapter)(uris=uris) def attach_to_tangle( self, trunk_transaction, branch_transaction, trytes, min_weight_magnitude=None, ): # type: (TransactionHash, TransactionHash, Iterable[TryteString], int) -> dict """ Attaches the specified transactions (trytes) to the Tangle by doing Proof of Work. You need to supply branchTransaction as well as trunkTransaction (basically the tips which you're going to validate and reference with this transaction) - both of which you'll get through the getTransactionsToApprove API call. The returned value is a different set of tryte values which you can input into :py:meth:`broadcast_transactions` and :py:meth:`store_transactions`. References: - https://iota.readme.io/docs/attachtotangle """ if min_weight_magnitude is None: min_weight_magnitude = self.default_min_weight_magnitude return core.AttachToTangleCommand(self.adapter)( trunkTransaction=trunk_transaction, branchTransaction=branch_transaction, minWeightMagnitude=min_weight_magnitude, trytes=trytes, ) def broadcast_transactions(self, trytes): # type: (Iterable[TryteString]) -> dict """ Broadcast a list of transactions to all neighbors. The input trytes for this call are provided by :py:meth:`attach_to_tangle`. References: - https://iota.readme.io/docs/broadcasttransactions """ return core.BroadcastTransactionsCommand(self.adapter)(trytes=trytes) def check_consistency(self, tails): # type: (Iterable[TransactionHash]) -> dict """ Used to ensure tail resolves to a consistent ledger which is necessary to validate before attempting promotionChecks transaction hashes for promotability. This is called with a pending transaction (or more of them) and it will tell you if it is still possible for this transaction (or all the transactions simultaneously if you give more than one) to be confirmed, or not (because it conflicts with another already confirmed transaction). :param tails: Transaction hashes. Must be tail transactions. :return: Dict containing the following:: { 'state': bool, 'info': str, This field will only exist set if `state` is False. } """ return core.CheckConsistencyCommand(self.adapter)(tails=tails, ) def find_transactions( self, bundles=None, addresses=None, tags=None, approvees=None, ): # type: (Optional[Iterable[TransactionHash]], Optional[Iterable[Address]], Optional[Iterable[Tag]], Optional[Iterable[TransactionHash]]) -> dict """ Find the transactions which match the specified input and return. All input values are lists, for which a list of return values (transaction hashes), in the same order, is returned for all individual elements. Using multiple of these input fields returns the intersection of the values. :param bundles: List of transaction IDs. :param addresses: List of addresses. :param tags: List of tags. :param approvees: List of approvee transaction IDs. References: - https://iota.readme.io/docs/findtransactions """ return core.FindTransactionsCommand(self.adapter)( bundles=bundles, addresses=addresses, tags=tags, approvees=approvees, ) def get_balances(self, addresses, threshold=100): # type: (Iterable[Address], int) -> dict """ Similar to :py:meth:`get_inclusion_states`. Returns the confirmed balance which a list of addresses have at the latest confirmed milestone. In addition to the balances, it also returns the milestone as well as the index with which the confirmed balance was determined. The balances are returned as a list in the same order as the addresses were provided as input. :param addresses: List of addresses to get the confirmed balance for. :param threshold: Confirmation threshold. References: - https://iota.readme.io/docs/getbalances """ return core.GetBalancesCommand(self.adapter)( addresses=addresses, threshold=threshold, ) def get_inclusion_states(self, transactions, tips): # type: (Iterable[TransactionHash], Iterable[TransactionHash]) -> dict """ Get the inclusion states of a set of transactions. This is for determining if a transaction was accepted and confirmed by the network or not. You can search for multiple tips (and thus, milestones) to get past inclusion states of transactions. :param transactions: List of transactions you want to get the inclusion state for. :param tips: List of tips (including milestones) you want to search for the inclusion state. References: - https://iota.readme.io/docs/getinclusionstates """ return core.GetInclusionStatesCommand(self.adapter)( transactions=transactions, tips=tips, ) def get_neighbors(self): # type: () -> dict """ Returns the set of neighbors the node is connected with, as well as their activity count. The activity counter is reset after restarting IRI. References: - https://iota.readme.io/docs/getneighborsactivity """ return core.GetNeighborsCommand(self.adapter)() def get_node_info(self): # type: () -> dict """ Returns information about the node. References: - https://iota.readme.io/docs/getnodeinfo """ return core.GetNodeInfoCommand(self.adapter)() def get_tips(self): # type: () -> dict """ Returns the list of tips (transactions which have no other transactions referencing them). References: - https://iota.readme.io/docs/gettips - https://iota.readme.io/docs/glossary#iota-terms """ return core.GetTipsCommand(self.adapter)() def get_transactions_to_approve(self, depth): # type: (int) -> dict """ Tip selection which returns ``trunkTransaction`` and ``branchTransaction``. :param depth: Determines how many bundles to go back to when finding the transactions to approve. The higher the depth value, the more "babysitting" the node will perform for the network (as it will confirm more transactions that way). References: - https://iota.readme.io/docs/gettransactionstoapprove """ return core.GetTransactionsToApproveCommand(self.adapter)(depth=depth) def get_trytes(self, hashes): # type: (Iterable[TransactionHash]) -> dict """ Returns the raw transaction data (trytes) of one or more transactions. References: - https://iota.readme.io/docs/gettrytes """ return core.GetTrytesCommand(self.adapter)(hashes=hashes) def interrupt_attaching_to_tangle(self): # type: () -> dict """ Interrupts and completely aborts the :py:meth:`attach_to_tangle` process. References: - https://iota.readme.io/docs/interruptattachingtotangle """ return core.InterruptAttachingToTangleCommand(self.adapter)() def remove_neighbors(self, uris): # type: (Iterable[Text]) -> dict """ Removes one or more neighbors from the node. Lasts until the node is restarted. :param uris: Use format ``udp://<ip address>:<port>``. Example: `remove_neighbors(['udp://example.com:14265'])` References: - https://iota.readme.io/docs/removeneighors """ return core.RemoveNeighborsCommand(self.adapter)(uris=uris) def store_transactions(self, trytes): # type: (Iterable[TryteString]) -> dict """ Store transactions into local storage. The input trytes for this call are provided by :py:meth:`attach_to_tangle`. References: - https://iota.readme.io/docs/storetransactions """ return core.StoreTransactionsCommand(self.adapter)(trytes=trytes) def were_addresses_spent_from(self, addresses): # type: (Iterable[Address]) -> dict """ Check if a list of addresses was ever spent from, in the current epoch, or in previous epochs. :param addresses: List of addresses to check. References: - https://iota.readme.io/docs/wereaddressesspentfrom """ return core.WereAddressesSpentFromCommand(self.adapter)( addresses=addresses, )
class MultisigIota(Iota): """ Extends the IOTA API so that it can send multi-signature transactions. **CAUTION:** Make sure you understand how multisig works before attempting to use it. If you are not careful, you could easily compromise the security of your private keys, send IOTAs to unspendable addresses, etc. References: - https://github.com/iotaledger/wiki/blob/master/multisigs.md """ commands = discover_commands('iota.multisig.commands') def create_multisig_address(self, digests): # type: (Iterable[Digest]) -> dict """ Generates a multisig address from a collection of digests. :param digests: Digests to use to create the multisig address. IMPORTANT: In order to spend IOTAs from a multisig address, the signature must be generated from the corresponding private keys in the exact same order. :return: Dict with the following items:: { 'address': MultisigAddress, The generated multisig address. } """ return commands.CreateMultisigAddressCommand(self.adapter)( digests = digests, ) def get_digests( self, index = 0, count = 1, security_level = AddressGenerator.DEFAULT_SECURITY_LEVEL, ): # type: (int, int, int) -> dict """ Generates one or more key digests from the seed. Digests are safe to share; use them to generate multisig addresses. :param index: The starting key index. :param count: Number of digests to generate. :param security_level: Number of iterations to use when generating new addresses. Larger values take longer, but the resulting signatures are more secure. This value must be between 1 and 3, inclusive. :return: Dict with the following items:: { 'digests': List[Digest], Always contains a list, even if only one digest was generated. } """ return commands.GetDigestsCommand(self.adapter)( seed = self.seed, index = index, count = count, securityLevel = security_level, ) def get_private_keys( self, index = 0, count = 1, security_level = AddressGenerator.DEFAULT_SECURITY_LEVEL, ): # type: (int, int, int) -> dict """ Generates one or more private keys from the seed. As the name implies, private keys should not be shared. However, in a few cases it may be necessary (e.g., for M-of-N transactions). :param index: The starting key index. :param count: Number of keys to generate. :param security_level: Number of iterations to use when generating new keys. Larger values take longer, but the resulting signatures are more secure. This value must be between 1 and 3, inclusive. :return: Dict with the following items:: { 'keys': List[PrivateKey], Always contains a list, even if only one key was generated. } References: - :py:class:`iota.crypto.signing.KeyGenerator` - https://github.com/iotaledger/wiki/blob/master/multisigs.md#how-m-of-n-works """ return commands.GetPrivateKeysCommand(self.adapter)( seed = self.seed, index = index, count = count, securityLevel = security_level, ) def prepare_multisig_transfer( self, transfers, multisig_input, change_address = None, ): # type: (Iterable[ProposedTransaction], MultisigAddress, Optional[Address]) -> dict """ Prepares a bundle that authorizes the spending of IOTAs from a multisig address. Note: if you want to spend IOTAs from non-multisig addresses, or if you want to create 0-value transfers (i.e., that don't require inputs), you can use :py:meth:`iota.api.Iota.prepare_transfer` instead. :param transfers: Transaction objects to prepare. Important: Must include at least one transaction that spends IOTAs (has a nonzero ``value``). If you want to prepare a bundle that does not spend any IOTAs, use :py:meth:`iota.api.prepare_transfer` instead. :param multisig_input: The multisig address to use as the input for the transfers. Note: a bundle may contain only one multisig input. :param change_address: If inputs are provided, any unspent amount will be sent to this address. If the bundle has no unspent inputs, ``change_address` is ignored. Unlike :py:meth:`iota.api.Iota.prepare_transfer`, this method will NOT generate a change address automatically. If there are unspent inputs and ``change_address`` is empty, an exception will be raised. This is because multisig transactions typically involve multiple individuals, and it would be unfair to the participants if we generated a change address automatically using the seed of whoever happened to run the ``prepare_multisig_transfer`` method! Note: this is not a substitute for due diligence! Always verify the details of every transaction in a bundle (including the change transaction) before signing the input(s)! :return: Dict containing the following values:: { 'trytes': List[TransactionTrytes], Finalized bundle, as trytes. The input transactions are not signed. } In order to authorize the spending of IOTAs from the multisig input, you must generate the correct private keys and invoke the :py:meth:`iota.crypto.types.PrivateKey.sign_input_at` method for each key, in the correct order. Once the correct signatures are applied, you can then perform proof of work (``attachToTangle``) and broadcast the bundle using :py:meth:`iota.api.Iota.send_trytes`. """ return commands.PrepareMultisigTransferCommand(self.adapter)( changeAddress = change_address, multisigInput = multisig_input, transfers = transfers, )
class Iota(StrictIota): """ Implements the core API, plus additional wrapper methods for common operations. References: - https://iota.readme.io/docs/getting-started - https://github.com/iotaledger/wiki/blob/master/api-proposal.md """ commands = discover_commands('iota.commands.extended') def __init__(self, adapter, seed=None, testnet=False): # type: (AdapterSpec, Optional[TrytesCompatible], bool) -> None """ :param seed: Seed used to generate new addresses. If not provided, a random one will be generated. Note: This value is never transferred to the node/network. """ super(Iota, self).__init__(adapter, testnet) self.seed = Seed(seed) if seed else Seed.random() self.helpers = Helpers(self) def broadcast_and_store(self, trytes): # type: (Iterable[TransactionTrytes]) -> dict """ Broadcasts and stores a set of transaction trytes. :return: Dict with the following structure:: { 'trytes': List[TransactionTrytes], List of TransactionTrytes that were broadcast. Same as the input ``trytes``. } References: - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#broadcastandstore """ return extended.BroadcastAndStoreCommand(self.adapter)(trytes=trytes) def get_account_data(self, start=0, stop=None, inclusion_states=False): # type: (int, Optional[int], bool) -> dict """ More comprehensive version of :py:meth:`get_transfers` that returns addresses and account balance in addition to bundles. This function is useful in getting all the relevant information of your account. :param start: Starting key index. :param stop: Stop before this index. Note that this parameter behaves like the ``stop`` attribute in a :py:class:`slice` object; the stop index is *not* included in the result. If ``None`` (default), then this method will check every address until it finds one without any transfers. :param inclusion_states: Whether to also fetch the inclusion states of the transfers. This requires an additional API call to the node, so it is disabled by default. :return: Dict containing the following values:: { 'addresses': List[Address], List of generated addresses. Note that this list may include unused addresses. 'balance': int, Total account balance. Might be 0. 'bundles': List[Bundle], List of bundles with transactions to/from this account. } """ return extended.GetAccountDataCommand(self.adapter)( seed=self.seed, start=start, stop=stop, inclusionStates=inclusion_states, ) def get_bundles(self, transaction): # type: (TransactionHash) -> dict """ Returns the bundle(s) associated with the specified transaction hash. :param transaction: Transaction hash. Must be a tail transaction. :return: Dict with the following structure:: { 'bundles': List[Bundle], List of matching bundles. Note that this value is always a list, even if only one bundle was found. } :raise: - :py:class:`iota.adapter.BadApiResponse` if any of the bundles fails validation. References: - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#getbundle """ return extended.GetBundlesCommand( self.adapter)(transaction=transaction) def get_inputs(self, start=0, stop=None, threshold=None): # type: (int, Optional[int], Optional[int]) -> dict """ Gets all possible inputs of a seed and returns them with the total balance. This is either done deterministically (by generating all addresses until :py:meth:`find_transactions` returns an empty result), or by providing a key range to search. :param start: Starting key index. Defaults to 0. :param stop: Stop before this index. Note that this parameter behaves like the ``stop`` attribute in a :py:class:`slice` object; the stop index is *not* included in the result. If ``None`` (default), then this method will not stop until it finds an unused address. :param threshold: If set, determines the minimum threshold for a successful result: - As soon as this threshold is reached, iteration will stop. - If the command runs out of addresses before the threshold is reached, an exception is raised. Note that this method does not attempt to "optimize" the result (e.g., smallest number of inputs, get as close to ``threshold`` as possible, etc.); it simply accumulates inputs in order until the threshold is met. If ``threshold`` is 0, the first address in the key range with a non-zero balance will be returned (if it exists). If ``threshold`` is ``None`` (default), this method will return **all** inputs in the specified key range. :return: Dict with the following structure:: { 'inputs': List[Address], Addresses with nonzero balances that can be used as inputs. 'totalBalance': int, Aggregate balance from all matching addresses. } Note that each Address in the result has its ``balance`` attribute set. Example:: response = iota.get_inputs(...) input0 = response['inputs'][0] # type: Address input0.balance # 42 :raise: - :py:class:`iota.adapter.BadApiResponse` if ``threshold`` is not met. Not applicable if ``threshold`` is ``None``. References: - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#getinputs """ return extended.GetInputsCommand(self.adapter)( seed=self.seed, start=start, stop=stop, threshold=threshold, ) def get_latest_inclusion(self, hashes): # type: (Iterable[TransactionHash]) -> Dict[TransactionHash, bool] """ Fetches the inclusion state for the specified transaction hashes, as of the latest milestone that the node has processed. Effectively, this is ``getNodeInfo`` + ``getInclusionStates``. :param hashes: Iterable of transaction hashes. :return: Dict with one boolean per transaction hash in ``hashes``:: { <TransactionHash>: <bool>, ... } """ return extended.GetLatestInclusionCommand(self.adapter)(hashes=hashes) def get_new_addresses( self, index=0, count=1, security_level=AddressGenerator.DEFAULT_SECURITY_LEVEL, checksum=False, ): # type: (int, Optional[int], int, bool) -> dict """ Generates one or more new addresses from the seed. :param index: Specify the index of the new address (must be >= 1). :param count: Number of addresses to generate (must be >= 1). Note: This is more efficient than calling ``get_new_address`` inside a loop. If ``None``, this method will scan the Tangle to find the next available unused address and return that. :param security_level: Number of iterations to use when generating new addresses. Larger values take longer, but the resulting signatures are more secure. This value must be between 1 and 3, inclusive. :param checksum: Specify whether to return the address with the checksum. Defaults to False. :return: Dict with the following items:: { 'addresses': List[Address], Always a list, even if only one address was generated. } References: - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#getnewaddress """ return extended.GetNewAddressesCommand(self.adapter)( count=count, index=index, securityLevel=security_level, checksum=checksum, seed=self.seed, ) def get_transfers(self, start=0, stop=None, inclusion_states=False): # type: (int, Optional[int], bool) -> dict """ Returns all transfers associated with the seed. :param start: Starting key index. :param stop: Stop before this index. Note that this parameter behaves like the ``stop`` attribute in a :py:class:`slice` object; the stop index is *not* included in the result. If ``None`` (default), then this method will check every address until it finds one without any transfers. :param inclusion_states: Whether to also fetch the inclusion states of the transfers. This requires an additional API call to the node, so it is disabled by default. :return: Dict containing the following values:: { 'bundles': List[Bundle], Matching bundles, sorted by tail transaction timestamp. } References: - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#gettransfers """ return extended.GetTransfersCommand(self.adapter)( seed=self.seed, start=start, stop=stop, inclusionStates=inclusion_states, ) def prepare_transfer(self, transfers, inputs=None, change_address=None): # type: (Iterable[ProposedTransaction], Optional[Iterable[Address]], Optional[Address]) -> dict """ Prepares transactions to be broadcast to the Tangle, by generating the correct bundle, as well as choosing and signing the inputs (for value transfers). :param transfers: Transaction objects to prepare. :param inputs: List of addresses used to fund the transfer. Ignored for zero-value transfers. If not provided, addresses will be selected automatically by scanning the Tangle for unspent inputs. Note: this could take awhile to complete. :param change_address: If inputs are provided, any unspent amount will be sent to this address. If not specified, a change address will be generated automatically. :return: Dict containing the following values:: { 'trytes': List[TransactionTrytes], Raw trytes for the transactions in the bundle, ready to be provided to :py:meth:`send_trytes`. } References: - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#preparetransfers """ return extended.PrepareTransferCommand(self.adapter)( seed=self.seed, transfers=transfers, inputs=inputs, changeAddress=change_address, ) def promote_transaction( self, transaction, depth, min_weight_magnitude=None, ): # type: (TransactionHash, int, Optional[int]) -> dict """ Promotes a transaction by adding spam on top of it. :return: Dict containing the following values:: { 'bundle': Bundle, The newly-published bundle. } """ if min_weight_magnitude is None: min_weight_magnitude = self.default_min_weight_magnitude return extended.PromoteTransactionCommand(self.adapter)( transaction=transaction, depth=depth, minWeightMagnitude=min_weight_magnitude, ) def replay_bundle( self, transaction, depth, min_weight_magnitude=None, ): # type: (TransactionHash, int, Optional[int]) -> dict """ Takes a tail transaction hash as input, gets the bundle associated with the transaction and then replays the bundle by attaching it to the Tangle. :param transaction: Transaction hash. Must be a tail. :param depth: Depth at which to attach the bundle. :param min_weight_magnitude: Min weight magnitude, used by the node to calibrate Proof of Work. If not provided, a default value will be used. :return: Dict containing the following values:: { 'trytes': List[TransactionTrytes], Raw trytes that were published to the Tangle. } References: - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#replaytransfer """ if min_weight_magnitude is None: min_weight_magnitude = self.default_min_weight_magnitude return extended.ReplayBundleCommand(self.adapter)( transaction=transaction, depth=depth, minWeightMagnitude=min_weight_magnitude, ) def send_transfer( self, depth, transfers, inputs=None, change_address=None, min_weight_magnitude=None, ): # type: (int, Iterable[ProposedTransaction], Optional[Iterable[Address]], Optional[Address], Optional[int]) -> dict """ Prepares a set of transfers and creates the bundle, then attaches the bundle to the Tangle, and broadcasts and stores the transactions. :param depth: Depth at which to attach the bundle. :param transfers: Transfers to include in the bundle. :param inputs: List of inputs used to fund the transfer. Not needed for zero-value transfers. :param change_address: If inputs are provided, any unspent amount will be sent to this address. If not specified, a change address will be generated automatically. :param min_weight_magnitude: Min weight magnitude, used by the node to calibrate Proof of Work. If not provided, a default value will be used. :return: Dict containing the following values:: { 'bundle': Bundle, The newly-published bundle. } References: - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#sendtransfer """ if min_weight_magnitude is None: min_weight_magnitude = self.default_min_weight_magnitude return extended.SendTransferCommand(self.adapter)( seed=self.seed, depth=depth, transfers=transfers, inputs=inputs, changeAddress=change_address, minWeightMagnitude=min_weight_magnitude, ) def send_trytes(self, trytes, depth, min_weight_magnitude=None): # type: (Iterable[TransactionTrytes], int, Optional[int]) -> dict """ Attaches transaction trytes to the Tangle, then broadcasts and stores them. :param trytes: Transaction encoded as a tryte sequence. :param depth: Depth at which to attach the bundle. :param min_weight_magnitude: Min weight magnitude, used by the node to calibrate Proof of Work. If not provided, a default value will be used. :return: Dict containing the following values:: { 'trytes': List[TransactionTrytes], Raw trytes that were published to the Tangle. } References: - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#sendtrytes """ if min_weight_magnitude is None: min_weight_magnitude = self.default_min_weight_magnitude return extended.SendTrytesCommand(self.adapter)( trytes=trytes, depth=depth, minWeightMagnitude=min_weight_magnitude, ) def is_reattachable(self, addresses): # type: (Iterable[Address]) -> dict """ This API function helps you to determine whether you should replay a transaction or make a completely new transaction with a different seed. What this function does, is it takes one or more input addresses (i.e. from spent transactions) as input and then checks whether any transactions with a value transferred are confirmed. If yes, it means that this input address has already been successfully used in a different transaction and as such you should no longer replay the transaction. :param addresses: List of addresses. :return: Dict containing the following values:: { 'reattachable': List[bool], Always a list, even if only one address was queried. } """ return extended.IsReattachableCommand( self.adapter)(addresses=addresses)
class StrictIota(object): """ API to send HTTP requests for communicating with an IOTA node. This implementation only exposes the "core" API methods. For a more feature-complete implementation, use :py:class:`Iota` instead. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference """ commands = discover_commands('iota.commands.core') def __init__(self, adapter, testnet=False, local_pow=False): # type: (AdapterSpec, bool, bool) -> None """ :param adapter: URI string or BaseAdapter instance. :param testnet: Whether to use testnet settings for this instance. """ super(StrictIota, self).__init__() if not isinstance(adapter, BaseAdapter): adapter = resolve_adapter(adapter) self.adapter = adapter # type: BaseAdapter # Note that the `local_pow` parameter is passed to adapter, # the api class has no notion about it. The reason being, # that this parameter is used in `AttachToTangeCommand` calls, # that is called from various api calls (`attach_to_tangle`, # `send_trytes` or `send_transfer`). Inside `AttachToTangeCommand`, # we no longer have access to the attributes of the API class, therefore # `local_pow` needs to be associated with the adapter. # Logically, `local_pow` will decide if the api call does pow # via pyota-pow extension, or sends the request to a node. # But technically, the parameter belongs to the adapter. self.adapter.set_local_pow(local_pow) self.testnet = testnet def __getattr__(self, command): # type: (Text) -> BaseCommand """ Creates a pre-configured command instance. This method will only return commands supported by the API class. If you want to execute an arbitrary API command, use :py:meth:`create_command`. :param command: The name of the command to create. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference """ # Fix an error when invoking :py:func:`help`. # https://github.com/iotaledger/iota.py/issues/41 if command == '__name__': # noinspection PyTypeChecker return None # Fix an error when invoking dunder methods. # https://github.com/iotaledger/iota.py/issues/206 if command.startswith("__"): # noinspection PyUnresolvedReferences return super(StrictIota, self).__getattr__(command) try: command_class = self.commands[command] except KeyError: raise InvalidCommand( '{cls} does not support {command!r} command.'.format( cls=type(self).__name__, command=command, ), ) return command_class(self.adapter) def create_command(self, command): # type: (Text) -> CustomCommand """ Creates a pre-configured CustomCommand instance. This method is useful for invoking undocumented or experimental methods, or if you just want to troll your node for awhile. :param command: The name of the command to create. """ return CustomCommand(self.adapter, command) def set_local_pow(self, local_pow): # type: (bool) -> None """ Sets the local_pow attribute of the adapter of the api instance. If it is true, attach_to_tangle command calls external interface to perform pow, instead of sending the request to a node. By default, it is set to false. This particular method is needed if one wants to change local_pow behavior dynamically. """ self.adapter.set_local_pow(local_pow) @property def default_min_weight_magnitude(self): # type: () -> int """ Returns the default ``min_weight_magnitude`` value to use for API requests. """ return 9 if self.testnet else 14 def add_neighbors(self, uris): # type: (Iterable[Text]) -> dict """ Add one or more neighbors to the node. Lasts until the node is restarted. :param uris: Use format ``<protocol>://<ip address>:<port>``. Example: ``add_neighbors(['udp://example.com:14265'])`` .. note:: These URIs are for node-to-node communication (e.g., weird things will happen if you specify a node's HTTP API URI here). References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#addneighbors """ return core.AddNeighborsCommand(self.adapter)(uris=uris) def attach_to_tangle( self, trunk_transaction, # type: TransactionHash branch_transaction, # type: TransactionHash trytes, # type: Iterable[TryteString] min_weight_magnitude=None, # type: Optional[int] ): # type: (...) -> dict """ Attaches the specified transactions (trytes) to the Tangle by doing Proof of Work. You need to supply branchTransaction as well as trunkTransaction (basically the tips which you're going to validate and reference with this transaction) - both of which you'll get through the getTransactionsToApprove API call. The returned value is a different set of tryte values which you can input into :py:meth:`broadcast_transactions` and :py:meth:`store_transactions`. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#attachtotangle """ if min_weight_magnitude is None: min_weight_magnitude = self.default_min_weight_magnitude return core.AttachToTangleCommand(self.adapter)( trunkTransaction=trunk_transaction, branchTransaction=branch_transaction, minWeightMagnitude=min_weight_magnitude, trytes=trytes, ) def broadcast_transactions(self, trytes): # type: (Iterable[TryteString]) -> dict """ Broadcast a list of transactions to all neighbors. The input trytes for this call are provided by :py:meth:`attach_to_tangle`. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#broadcasttransactions """ return core.BroadcastTransactionsCommand(self.adapter)(trytes=trytes) def check_consistency(self, tails): # type: (Iterable[TransactionHash]) -> dict """ Used to ensure tail resolves to a consistent ledger which is necessary to validate before attempting promotionChecks transaction hashes for promotability. This is called with a pending transaction (or more of them) and it will tell you if it is still possible for this transaction (or all the transactions simultaneously if you give more than one) to be confirmed, or not (because it conflicts with another already confirmed transaction). :param tails: Transaction hashes. Must be tail transactions. :return: Dict with the following structure:: { 'state': bool, 'info': str, This field will only exist set if ``state`` is ``False``. } References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#checkconsistency """ return core.CheckConsistencyCommand(self.adapter)(tails=tails, ) def find_transactions( self, bundles=None, # type: Optional[Iterable[BundleHash]] addresses=None, # type: Optional[Iterable[Address]] tags=None, # type: Optional[Iterable[Tag]] approvees=None, # type: Optional[Iterable[TransactionHash]] ): # type: (...) -> dict """ Find the transactions which match the specified input and return. All input values are lists, for which a list of return values (transaction hashes), in the same order, is returned for all individual elements. Using multiple of these input fields returns the intersection of the values. :param bundles: List of bundle IDs. :param addresses: List of addresses. :param tags: List of tags. :param approvees: List of approvee transaction IDs. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#findtransactions """ return core.FindTransactionsCommand(self.adapter)( bundles=bundles, addresses=addresses, tags=tags, approvees=approvees, ) def get_balances( self, addresses, # type: Iterable[Address] threshold=100, # type: int tips=None, # type: Optional[Iterable[TransactionHash]] ): # type: (...) -> dict """ Similar to :py:meth:`get_inclusion_states`. Returns the confirmed balance which a list of addresses have at the latest confirmed milestone. In addition to the balances, it also returns the milestone as well as the index with which the confirmed balance was determined. The balances are returned as a list in the same order as the addresses were provided as input. :param addresses: List of addresses to get the confirmed balance for. :param threshold: Confirmation threshold between 0 and 100. :param tips: Tips whose history of transactions to traverse to find the balance. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getbalances """ return core.GetBalancesCommand(self.adapter)( addresses=addresses, threshold=threshold, tips=tips, ) def get_inclusion_states(self, transactions, tips): # type: (Iterable[TransactionHash], Iterable[TransactionHash]) -> dict """ Get the inclusion states of a set of transactions. This is for determining if a transaction was accepted and confirmed by the network or not. You can search for multiple tips (and thus, milestones) to get past inclusion states of transactions. :param transactions: List of transactions you want to get the inclusion state for. :param tips: List of tips (including milestones) you want to search for the inclusion state. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getinclusionstates """ return core.GetInclusionStatesCommand(self.adapter)( transactions=transactions, tips=tips, ) def get_missing_transactions(self): # type: () -> dict """ Returns all transaction hashes that a node is currently requesting from its neighbors. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getmissingtransactions """ return core.GetMissingTransactionsCommand(self.adapter)() def get_neighbors(self): # type: () -> dict """ Returns the set of neighbors the node is connected with, as well as their activity count. The activity counter is reset after restarting IRI. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getneighbors """ return core.GetNeighborsCommand(self.adapter)() def get_node_api_configuration(self): # type: () -> dict """ Returns a node's API configuration settings. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getnodeapiconfiguration """ return core.GetNodeAPIConfigurationCommand(self.adapter)() def get_node_info(self): # type: () -> dict """ Returns information about the node. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getnodeinfo """ return core.GetNodeInfoCommand(self.adapter)() def get_tips(self): # type: () -> dict """ Returns the list of tips (transactions which have no other transactions referencing them). References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#gettips - https://docs.iota.org/docs/dev-essentials/0.1/references/glossary """ return core.GetTipsCommand(self.adapter)() def get_transactions_to_approve(self, depth, reference=None): # type: (int, Optional[TransactionHash]) -> dict """ Tip selection which returns ``trunkTransaction`` and ``branchTransaction``. :param depth: Determines how many bundles to go back to when finding the transactions to approve. The higher the depth value, the more "babysitting" the node will perform for the network (as it will confirm more transactions that way). :param reference: Transaction hash from which to start the weighted random walk. Use this parameter to make sure the returned tip transaction hashes approve a given reference transaction. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#gettransactionstoapprove """ return core.GetTransactionsToApproveCommand(self.adapter)( depth=depth, reference=reference, ) def get_trytes(self, hashes): # type: (Iterable[TransactionHash]) -> dict """ Returns the raw transaction data (trytes) of one or more transactions. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#gettrytes """ return core.GetTrytesCommand(self.adapter)(hashes=hashes) def interrupt_attaching_to_tangle(self): # type: () -> dict """ Interrupts and completely aborts the :py:meth:`attach_to_tangle` process. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#interruptattachingtotangle """ return core.InterruptAttachingToTangleCommand(self.adapter)() def remove_neighbors(self, uris): # type: (Iterable[Text]) -> dict """ Removes one or more neighbors from the node. Lasts until the node is restarted. :param uris: Use format ``<protocol>://<ip address>:<port>``. Example: `remove_neighbors(['udp://example.com:14265'])` References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#removeneighbors """ return core.RemoveNeighborsCommand(self.adapter)(uris=uris) def store_transactions(self, trytes): # type: (Iterable[TryteString]) -> dict """ Store transactions into local storage. The input trytes for this call are provided by :py:meth:`attach_to_tangle`. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#storetransactions """ return core.StoreTransactionsCommand(self.adapter)(trytes=trytes) def were_addresses_spent_from(self, addresses): # type: (Iterable[Address]) -> dict """ Check if a list of addresses was ever spent from, in the current epoch, or in previous epochs. :param addresses: List of addresses to check. References: - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#wereaddressesspentfrom """ return core.WereAddressesSpentFromCommand(self.adapter)( addresses=addresses, )