def connect( self, funds: typing.TokenAmount, initial_channel_target: int = 3, joinable_funds_target: float = 0.4, ) -> None: """Connect to the network. Subsequent calls to `connect` are allowed, but will only affect the spendable funds and the connection strategy parameters for the future. `connect` will not close any channels. Note: the ConnectionManager does not discriminate manually opened channels from automatically opened ones. If the user manually opened channels, those deposit amounts will affect the funding per channel and the number of new channels opened. Args: funds: Target amount of tokens spendable to join the network. initial_channel_target: Target number of channels to open. joinable_funds_target: Amount of funds not initially assigned. """ token = self.raiden.proxy_manager.token(self.token_address) token_balance = token.balance_of(self.raiden.address) if token_balance < funds: raise InvalidAmount( f"Insufficient balance for token {to_checksum_address(self.token_address)}" ) if funds <= 0: raise InvalidAmount("The funds to use in the connection need to be a positive integer") if joinable_funds_target < 0 or joinable_funds_target > 1: raise InvalidAmount( f"joinable_funds_target should be between 0 and 1. Given: {joinable_funds_target}" ) with self.lock: self.funds = funds self.initial_channel_target = initial_channel_target self.joinable_funds_target = joinable_funds_target log_open_channels(self.raiden, self.registry_address, self.token_address, funds) qty_network_channels = views.count_token_network_channels( views.state_from_raiden(self.raiden), self.registry_address, self.token_address ) if not qty_network_channels: log.info( "Bootstrapping token network.", node=to_checksum_address(self.raiden.address), network_id=to_checksum_address(self.registry_address), token_id=to_checksum_address(self.token_address), ) self.api.channel_open( self.registry_address, self.token_address, self.BOOTSTRAP_ADDR ) else: self._open_channels()
def transfer_async(self, token_address, amount, target, identifier=None): # pylint: disable=too-many-arguments if not isinstance(amount, int): raise InvalidAmount('Amount not a number') if amount <= 0: raise InvalidAmount('Amount negative') if not isaddress(token_address) or token_address not in self.tokens: raise InvalidAddress('token address is not valid.') if not isaddress(target): raise InvalidAddress('target address is not valid.') graph = self.raiden.token_to_channelgraph[token_address] if not graph.has_path(self.raiden.address, target): raise NoPathError('No path to address found') log.debug('initiating transfer', initiator=pex(self.raiden.address), target=pex(target), token=pex(token_address), amount=amount, identifier=identifier) async_result = self.raiden.mediated_transfer_async( token_address, amount, target, identifier, ) return async_result
def transfer_async(self, token_address, amount, target, identifier=None): if not isinstance(amount, int): raise InvalidAmount('Amount not a number') if amount <= 0: raise InvalidAmount('Amount negative') if not isaddress(token_address): raise InvalidAddress('token address is not valid.') if not isaddress(target): raise InvalidAddress('target address is not valid.') valid_tokens = views.get_token_network_addresses_for( views.state_from_raiden(self.raiden), self.raiden.default_registry.address, ) if token_address not in valid_tokens: raise UnknownTokenAddress('Token address is not known.') log.debug('initiating transfer', initiator=pex(self.raiden.address), target=pex(target), token=pex(token_address), amount=amount, identifier=identifier) async_result = self.raiden.mediated_transfer_async( token_address, amount, target, identifier, ) return async_result
def transfer_async(self, token_address, amount, target, identifier=None): # pylint: disable=too-many-arguments if not isinstance(amount, (int, long)): raise InvalidAmount('Amount not a number') if amount <= 0: raise InvalidAmount('Amount negative') if not isaddress(token_address) or token_address not in self.tokens: raise InvalidAddress('token address is not valid.') if not isaddress(target): raise InvalidAddress('target address is not valid.') graph = self.raiden.channelgraphs[token_address] if not graph.has_path(self.raiden.address, target): raise NoPathError('No path to address found') async_result = self.raiden.transfer_async( token_address, amount, target, identifier=identifier, ) return async_result
def connect( self, funds: typing.TokenAmount, initial_channel_target: int = 3, joinable_funds_target: float = 0.4, ): """Connect to the network. Subsequent calls to `connect` are allowed, but will only affect the spendable funds and the connection strategy parameters for the future. `connect` will not close any channels. Note: the ConnectionManager does not discriminate manually opened channels from automatically opened ones. If the user manually opened channels, those deposit amounts will affect the funding per channel and the number of new channels opened. Args: funds: Target amount of tokens spendable to join the network. initial_channel_target: Target number of channels to open. joinable_funds_target: Amount of funds not initially assigned. """ token = self.raiden.chain.token(self.token_address) token_balance = token.balance_of(self.raiden.address) if token_balance < funds: raise InvalidAmount( f'Insufficient balance for token {pex(self.token_address)}', ) if funds <= 0: raise InvalidAmount( 'The funds to use in the connection need to be a positive integer', ) with self.lock: self.funds = funds self.initial_channel_target = initial_channel_target self.joinable_funds_target = joinable_funds_target log_open_channels(self.raiden, self.registry_address, self.token_address, funds) qty_network_channels = views.count_token_network_channels( views.state_from_raiden(self.raiden), self.registry_address, self.token_address, ) if not qty_network_channels: log.debug('bootstrapping token network.') # make ourselves visible self.api.channel_open( self.registry_address, self.token_address, self.BOOTSTRAP_ADDR, ) else: self._open_channels()
def transfer_async( self, registry_address: typing.PaymentNetworkID, token_address: typing.TokenAddress, amount: typing.TokenAmount, target: typing.Address, identifier: typing.PaymentID = None, ): if not isinstance(amount, int): raise InvalidAmount('Amount not a number') if amount <= 0: raise InvalidAmount('Amount negative') if not is_binary_address(token_address): raise InvalidAddress('token address is not valid.') if not is_binary_address(target): raise InvalidAddress('target address is not valid.') valid_tokens = views.get_token_network_addresses_for( views.state_from_raiden(self.raiden), registry_address, ) if token_address not in valid_tokens: raise UnknownTokenAddress('Token address is not known.') log.debug( 'Initiating transfer', initiator=pex(self.raiden.address), target=pex(target), token=pex(token_address), amount=amount, identifier=identifier, ) payment_network_identifier = self.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state=views.state_from_raiden(self.raiden), payment_network_id=payment_network_identifier, token_address=token_address, ) async_result = self.raiden.mediated_transfer_async( token_network_identifier=token_network_identifier, amount=amount, target=target, identifier=identifier, ) return async_result
def connect( self, funds: typing.TokenAmount, initial_channel_target: int = 3, joinable_funds_target: float = 0.4, ) -> None: """Connect to the network. Subsequent calls to `connect` are allowed, but will only affect the spendable funds and the connection strategy parameters for the future. `connect` will not close any channels. Note: the ConnectionManager does not discriminate manually opened channels from automatically opened ones. If the user manually opened channels, those deposit amounts will affect the funding per channel and the number of new channels opened. Args: funds: Target amount of tokens spendable to join the network. initial_channel_target: Target number of channels to open. joinable_funds_target: Amount of funds not initially assigned. """ confirmed_block_identifier = views.get_confirmed_blockhash(self.raiden) token = self.raiden.proxy_manager.token(self.token_address, confirmed_block_identifier) token_balance = token.balance_of(self.raiden.address) if token_balance < funds: raise InvalidAmount( f"Insufficient balance for token {to_checksum_address(self.token_address)}" ) if funds <= 0: raise InvalidAmount( "The funds to use in the connection need to be a positive integer" ) if joinable_funds_target < 0 or joinable_funds_target > 1: raise InvalidAmount( f"joinable_funds_target should be between 0 and 1. Given: {joinable_funds_target}" ) with self.lock: self.funds = funds self.initial_channel_target = initial_channel_target self.joinable_funds_target = joinable_funds_target log_open_channels(self.raiden, self.registry_address, self.token_address, funds) have_online_partners, potential_partners = self._have_online_channels_to_connect_to( ) if not have_online_partners: bootstrap_address = (self.BOOTSTRAP_ADDR if len(potential_partners) == 0 else random.choice(potential_partners)) log.info( "Bootstrapping token network.", node=to_checksum_address(self.raiden.address), network_id=to_checksum_address(self.registry_address), token_id=to_checksum_address(self.token_address), bootstrap_address=to_checksum_address(bootstrap_address), ) try: self.api.channel_open( registry_address=self.registry_address, token_address=self.token_address, partner_address=bootstrap_address, ) except DuplicatedChannelError: # If we have none else to connect to and connect got called twice # then it's possible to already have channel with the bootstrap node. # In that case do nothing pass else: self._open_channels()
def transfer_async( self, registry_address: typing.PaymentNetworkID, token_address: typing.TokenAddress, amount: typing.TokenAmount, target: typing.Address, identifier: typing.PaymentID = None, secret: typing.Secret = None, secret_hash: typing.SecretHash = None, ): if not isinstance(amount, int): raise InvalidAmount('Amount not a number') if amount <= 0: raise InvalidAmount('Amount negative') if not is_binary_address(token_address): raise InvalidAddress('token address is not valid.') if not is_binary_address(target): raise InvalidAddress('target address is not valid.') if secret is not None: if len(secret) != SECRET_HEXSTRING_LENGTH: raise InvalidSecretOrSecretHash( 'secret length should be ' + str(SECRET_HEXSTRING_LENGTH) + '.', ) if not is_hex(secret): raise InvalidSecretOrSecretHash( 'provided secret is not an hexadecimal string.') secret = to_bytes(hexstr=secret) if secret_hash is not None: if len(secret_hash) != SECRET_HASH_HEXSTRING_LENGTH: raise InvalidSecretOrSecretHash( 'secret_hash length should be ' + str(SECRET_HASH_HEXSTRING_LENGTH) + '.', ) if not is_hex(secret_hash): raise InvalidSecretOrSecretHash( 'secret_hash is not an hexadecimal string.') secret_hash = to_bytes(hexstr=secret_hash) if secret is None and secret_hash is not None: raise InvalidSecretOrSecretHash( 'secret_hash without a secret is not supported yet.') if secret is not None and secret_hash is not None and secret_hash != sha3( secret): raise InvalidSecretOrSecretHash( 'provided secret and secret_hash do not match.') valid_tokens = views.get_token_identifiers( views.state_from_raiden(self.raiden), registry_address, ) if token_address not in valid_tokens: raise UnknownTokenAddress('Token address is not known.') log.debug( 'Initiating transfer', initiator=pex(self.raiden.address), target=pex(target), token=pex(token_address), amount=amount, identifier=identifier, ) payment_network_identifier = self.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state=views.state_from_raiden(self.raiden), payment_network_id=payment_network_identifier, token_address=token_address, ) payment_status = self.raiden.mediated_transfer_async( token_network_identifier=token_network_identifier, amount=amount, target=target, identifier=identifier, secret=secret, secret_hash=secret_hash, ) return payment_status
def transfer_async( self, registry_address: PaymentNetworkID, token_address: TokenAddress, amount: TokenAmount, target: Address, identifier: PaymentID = None, secret: Secret = None, secrethash: SecretHash = None, ): current_state = views.state_from_raiden(self.raiden) payment_network_identifier = self.raiden.default_registry.address if not isinstance(amount, int): raise InvalidAmount("Amount not a number") if amount <= 0: raise InvalidAmount("Amount negative") if amount > UINT256_MAX: raise InvalidAmount("Amount too large") if not is_binary_address(token_address): raise InvalidAddress("token address is not valid.") if token_address not in views.get_token_identifiers(current_state, registry_address): raise UnknownTokenAddress("Token address is not known.") if not is_binary_address(target): raise InvalidAddress("target address is not valid.") valid_tokens = views.get_token_identifiers( views.state_from_raiden(self.raiden), registry_address ) if token_address not in valid_tokens: raise UnknownTokenAddress("Token address is not known.") if secret is not None and not isinstance(secret, typing.T_Secret): raise InvalidSecret("secret is not valid.") if secrethash is not None and not isinstance(secrethash, typing.T_SecretHash): raise InvalidSecretHash("secrethash is not valid.") log.debug( "Initiating transfer", initiator=pex(self.raiden.address), target=pex(target), token=pex(token_address), amount=amount, identifier=identifier, ) token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state=current_state, payment_network_id=payment_network_identifier, token_address=token_address, ) payment_status = self.raiden.mediated_transfer_async( token_network_identifier=token_network_identifier, amount=amount, target=target, identifier=identifier, secret=secret, secrethash=secrethash, ) return payment_status
def transfer_async( self, registry_address: TokenNetworkRegistryAddress, token_address: TokenAddress, amount: PaymentAmount, target: TargetAddress, identifier: PaymentID = None, secret: Secret = None, secrethash: SecretHash = None, lock_timeout: BlockTimeout = None, ) -> "PaymentStatus": current_state = views.state_from_raiden(self.raiden) token_network_registry_address = self.raiden.default_registry.address if not isinstance(amount, int): # pragma: no unittest raise InvalidAmount("Amount not a number") if Address(target) == self.address: raise SamePeerAddress("Address must be different than ours") if amount <= 0: raise InvalidAmount("Amount negative") if amount > UINT256_MAX: raise InvalidAmount("Amount too large") if not is_binary_address(token_address): raise InvalidBinaryAddress("token address is not valid.") if token_address not in views.get_token_identifiers( current_state, registry_address): raise UnknownTokenAddress("Token address is not known.") if not is_binary_address(target): raise InvalidBinaryAddress("target address is not valid.") valid_tokens = views.get_token_identifiers( views.state_from_raiden(self.raiden), registry_address) if token_address not in valid_tokens: raise UnknownTokenAddress("Token address is not known.") if secret is not None and not isinstance(secret, T_Secret): raise InvalidSecret("secret is not valid.") if secrethash is not None and not isinstance(secrethash, T_SecretHash): raise InvalidSecretHash("secrethash is not valid.") if identifier is None: identifier = create_default_identifier() if identifier <= 0: raise InvalidPaymentIdentifier( "Payment identifier cannot be 0 or negative") if identifier > UINT64_MAX: raise InvalidPaymentIdentifier("Payment identifier is too large") log.debug( "Initiating transfer", initiator=to_checksum_address(self.raiden.address), target=to_checksum_address(target), token=to_checksum_address(token_address), amount=amount, identifier=identifier, ) token_network_address = views.get_token_network_address_by_token_address( chain_state=current_state, token_network_registry_address=token_network_registry_address, token_address=token_address, ) if token_network_address is None: raise UnknownTokenAddress( f"Token {to_checksum_address(token_address)} is not registered " f"with the network {to_checksum_address(registry_address)}.") payment_status = self.raiden.mediated_transfer_async( token_network_address=token_network_address, amount=amount, target=target, identifier=identifier, secret=secret, secrethash=secrethash, lock_timeout=lock_timeout, ) return payment_status
def transfer_async( self, registry_address: PaymentNetworkID, token_address: TokenAddress, amount: TokenAmount, target: Address, identifier: PaymentID = None, secret: Secret = None, secrethash: SecretHash = None, ): if not isinstance(amount, int): raise InvalidAmount("Amount not a number") if amount <= 0: raise InvalidAmount("Amount negative") if not is_binary_address(token_address): raise InvalidAddress("token address is not valid.") if not is_binary_address(target): raise InvalidAddress("target address is not valid.") if secret is not None: if len(secret) != SECRET_HEXSTRING_LENGTH: raise InvalidSecretOrSecretHash( "secret length should be " + str(SECRET_HEXSTRING_LENGTH) + "." ) if not is_hex(secret): raise InvalidSecretOrSecretHash("provided secret is not an hexadecimal string.") secret = to_bytes(hexstr=secret) if secrethash is not None: if len(secrethash) != SECRETHASH_HEXSTRING_LENGTH: raise InvalidSecretOrSecretHash( "secret_hash length should be " + str(SECRETHASH_HEXSTRING_LENGTH) + "." ) if not is_hex(secrethash): raise InvalidSecretOrSecretHash("secret_hash is not an hexadecimal string.") secrethash = to_bytes(hexstr=secrethash) # if both secret and secrethash were provided we check that sha3(secret) # matches the secerthash. Note that it is valid to provide a secert_hash # without providing a secret if secret is not None and secrethash is not None and secrethash != sha3(secret): raise InvalidSecretOrSecretHash("provided secret and secret_hash do not match.") valid_tokens = views.get_token_identifiers( views.state_from_raiden(self.raiden), registry_address ) if token_address not in valid_tokens: raise UnknownTokenAddress("Token address is not known.") log.debug( "Initiating transfer", initiator=pex(self.raiden.address), target=pex(target), token=pex(token_address), amount=amount, identifier=identifier, ) payment_network_identifier = self.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state=views.state_from_raiden(self.raiden), payment_network_id=payment_network_identifier, token_address=token_address, ) payment_status = self.raiden.mediated_transfer_async( token_network_identifier=token_network_identifier, amount=amount, target=target, identifier=identifier, secret=secret, secrethash=secrethash, ) return payment_status