Beispiel #1
0
    def _swap_close(self, context, signer_pubkey, swap_close_payload):
        """
        Bob or Alice closes the swap by providing the secret key which matches secret lock.
        Requires "is_approved = True"
        Requires hash of secret key to match secret lock

        """
        swap_info = self.get_swap_info_from_swap_id(context,
                                                    swap_close_payload.swap_id)

        if not swap_info.secret_lock:
            raise InvalidTransaction(
                'Secret lock is required to close the swap!')

        if web3_hash(swap_close_payload.secret_key) != swap_info.secret_lock:
            raise InvalidTransaction(
                'Secret key doesn\'t match specified secret lock!')

        if swap_info.is_initiator and swap_info.state != AtomicSwapInfo.APPROVED:
            raise InvalidTransaction(
                'Transaction cannot be closed before it\'s approved.')

        transfer_payload = AccountClient.get_transfer_payload(
            swap_info.receiver_address, swap_info.amount)
        token_updated_state = AccountHandler()._transfer_from_address(
            context, ZERO_ADDRESS, transfer_payload)
        swap_info.state = AtomicSwapInfo.CLOSED

        return {**self.get_state_update(swap_info), **token_updated_state}
Beispiel #2
0
    def test_transfer_success_no_state_address2(self):
        ACCOUNT_AMOUNT1 = 500
        TRANSFER_VALUE = 200
        signature = self.send_transaction(
            AccountMethod.TRANSFER,
            AccountClient.get_transfer_payload(self.account_address2,
                                               TRANSFER_VALUE),
            [self.account_address1, self.account_address2])
        self.expect_get({
            self.account_address1:
            AccountClient.get_account_model(ACCOUNT_AMOUNT1),
            self.account_address2:
            None
        })

        self.expect_set(
            signature, AccountMethod.TRANSFER, {
                self.account_address1:
                AccountClient.get_account_model(ACCOUNT_AMOUNT1 -
                                                TRANSFER_VALUE),
                self.account_address2:
                AccountClient.get_account_model(0 + TRANSFER_VALUE)
            })

        self.expect_ok()
Beispiel #3
0
    def _swap_expire(self, context, signer_pubkey, swap_expire_payload):
        """
        Transaction initiator (Alice) decides to withdraw deposit in 24 hours, or Bob in 48 hours

        """

        swap_info = self.get_swap_info_from_swap_id(
            context, swap_expire_payload.swap_id)

        if AccountHandler().make_address_from_data(
                signer_pubkey) != swap_info.sender_address:
            raise InvalidTransaction(
                'Signer is not the one who opened the swap.')

        now = datetime.datetime.utcnow()
        created_at = self.get_datetime_from_timestamp(swap_info.created_at)
        time_delta = INITIATOR_TIME_DELTA_LOCK if swap_info.is_initiator else NON_INITIATOR_TIME_DELTA_LOCK
        if (created_at + time_delta) > now:
            intiator_name = "initiator" if swap_info.is_initiator else "non initiator"
            raise InvalidTransaction(
                'Swap {} needs to wait {} hours since timestamp: {} to withdraw.'
                .format(intiator_name, INTIATOR_TIME_LOCK,
                        swap_info.created_at))

        swap_info.state = AtomicSwapInfo.EXPIRED

        transfer_payload = AccountClient.get_transfer_payload(
            swap_info.sender_address, swap_info.amount)
        token_updated_state = AccountHandler()._transfer_from_address(
            context, ZERO_ADDRESS, transfer_payload)

        return {**self.get_state_update(swap_info), **token_updated_state}
Beispiel #4
0
 def test_transfer_fail_to_zeroaddress(self):
     TRANSFER_VALUE = 200
     self.send_transaction(
         AccountMethod.TRANSFER,
         AccountClient.get_transfer_payload(GENESIS_ADDRESS,
                                            TRANSFER_VALUE),
         [self.account_address1, self.account_address2])
     self.expect_invalid_transaction()
    def test_transfer_fail_no_state_address1(self):
        ACCOUNT_AMOUNT2 = 500
        TRANSFER_VALUE = 200
        self.send_transaction(AccountMethod.TRANSFER,
                              AccountClient.get_transfer_payload(self.account_address2, TRANSFER_VALUE),
                              [self.account_address1, self.account_address2])
        self.expect_get({self.account_address1: None, self.account_address2: AccountClient.get_account_model(0)})

        self.expect_invalid_transaction()
    def test_transfer_fail_to_zeroaddress(self):
        ACCOUNT_AMOUNT1 = 500
        TRANSFER_VALUE = 200
        self.send_transaction(AccountMethod.TRANSFER,
                              AccountClient.get_transfer_payload(GENESIS_ADDRESS, TRANSFER_VALUE),
                              [self.account_address1, self.account_address2])
        # self.expect_get({self.account_address1: AccountClient.get_account_model(ACCOUNT_AMOUNT1)})

        self.expect_invalid_transaction()
Beispiel #7
0
    def _swap_init(self, context, signer_pubkey, swap_init_payload):
        """
        if SecretLockOptionalBob is provided, Bob uses _swap_init to respond to requested swap
        Otherwise, Alice uses _swap_init to request a swap and thus, Bob can't receive funds until Alice "approves".
        """
        address_swap_info_is_stored_by = self.make_address_from_data(swap_init_payload.swap_id)
        swap_information = get_data(context, AtomicSwapInfo, address_swap_info_is_stored_by)

        if swap_information:
            raise InvalidTransaction('Atomic swap ID has already been taken, please use a different one.')

        block_info = self._get_latest_block_info(context)
        block_time = block_info.timestamp

        swap_information = AtomicSwapInfo()
        swap_information.swap_id = swap_init_payload.swap_id
        swap_information.state = AtomicSwapInfo.OPENED
        swap_information.amount = swap_init_payload.amount
        swap_information.created_at = block_time
        swap_information.secret_lock = swap_init_payload.secret_lock_by_solicitor
        swap_information.email_address_encrypted_optional = swap_init_payload.email_address_encrypted_by_initiator
        swap_information.sender_address = AccountHandler().make_address_from_data(signer_pubkey)
        swap_information.sender_address_non_local = swap_init_payload.sender_address_non_local
        swap_information.receiver_address = swap_init_payload.receiver_address
        swap_information.is_initiator = not swap_init_payload.secret_lock_by_solicitor

        commission_amount = int(_get_setting_value(context, SETTINGS_SWAP_COMMISSION))
        if commission_amount < 0:
            raise InvalidTransaction('Wrong commission address.')

        swap_total_amount = swap_information.amount + commission_amount

        account = get_data(context, Account, swap_information.sender_address)

        if account is None:
            account = Account()

        if account.balance < swap_total_amount:
            raise InvalidTransaction(
                f'Not enough balance to perform the transaction in the amount (with a commission) {swap_total_amount}.'
            )

        transfer_payload = AccountClient.get_transfer_payload(ZERO_ADDRESS, commission_amount)

        transfer_state = AccountHandler()._transfer_from_address(
            context, swap_information.sender_address, transfer_payload,
        )

        sender_account = transfer_state.get(swap_information.sender_address)
        sender_account.balance -= swap_information.amount

        return {
            address_swap_info_is_stored_by: swap_information,
            **transfer_state,
        }
    def test_transfer_fail_no_balance(self):
        ACCOUNT_AMOUNT1 = 200
        ACCOUNT_AMOUNT2 = 500
        TRANSFER_VALUE = ACCOUNT_AMOUNT1 + 1
        self.send_transaction(AccountMethod.TRANSFER,
                              AccountClient.get_transfer_payload(self.account_address2, TRANSFER_VALUE),
                              [self.account_address1, self.account_address2])
        self.expect_get({self.account_address1: AccountClient.get_account_model(ACCOUNT_AMOUNT1),
                         self.account_address2: AccountClient.get_account_model(ACCOUNT_AMOUNT2)})

        self.expect_invalid_transaction()
    def test_transfer_success(self):
        ACCOUNT_AMOUNT1 = 1000
        ACCOUNT_AMOUNT2 = 500
        TRANSFER_VALUE = ACCOUNT_AMOUNT1

        self.send_transaction(AccountMethod.TRANSFER,
                              AccountClient.get_transfer_payload(self.account_address2, TRANSFER_VALUE),
                              [self.account_address1, self.account_address2])

        self.expect_set(self.transfer(self.account_address1, ACCOUNT_AMOUNT1,
                                      self.account_address2, ACCOUNT_AMOUNT2, TRANSFER_VALUE))

        self.expect_ok()
Beispiel #10
0
    def test_transfer_success(self):
        ACCOUNT_AMOUNT1 = 1000
        ACCOUNT_AMOUNT2 = 500
        TRANSFER_VALUE = ACCOUNT_AMOUNT1

        LOGGER.info(f'test_transfer_success signature ')
        signature = self.send_transaction(
            AccountMethod.TRANSFER,
            AccountClient.get_transfer_payload(self.account_address2,
                                               TRANSFER_VALUE),
            [self.account_address1, self.account_address2])

        LOGGER.info(f'test_transfer_success signature {signature}')
        self.expect_set(
            signature, AccountMethod.TRANSFER,
            self.transfer(self.account_address1, ACCOUNT_AMOUNT1,
                          self.account_address2, ACCOUNT_AMOUNT2,
                          TRANSFER_VALUE))

        self.expect_ok()
Beispiel #11
0
    def _swap_init(self, context, signer_pubkey, swap_init_payload):
        """
        if SecretLockOptionalBob is provided, Bob uses _swap_init to respond to requested swap
        Otherwise, Alice uses _swap_init to request a swap and thus, Bob can't receive funds until Alice "approves".
        """
        LOGGER.info("0. Check if swap ID already exists")
        # 0. Check if swap ID already exists
        if self.get_swap_info_from_swap_id(context,
                                           swap_init_payload.swap_id,
                                           to_raise_exception=False):
            raise InvalidTransaction(
                'Atomic swap ID has already been taken, please use a different one!'
            )
        # END

        swap_info = AtomicSwapInfo()
        swap_info.swap_id = swap_init_payload.swap_id
        swap_info.state = AtomicSwapInfo.OPENED
        swap_info.amount = swap_init_payload.amount
        swap_info.created_at = swap_init_payload.created_at
        swap_info.email_address_encrypted_optional = swap_init_payload.email_address_encrypted_by_initiator
        swap_info.sender_address = AccountHandler().make_address_from_data(
            signer_pubkey)
        swap_info.sender_address_non_local = swap_init_payload.sender_address_non_local
        swap_info.receiver_address = swap_init_payload.receiver_address

        if not AccountHandler().is_handler_address(swap_info.receiver_address):
            raise InvalidTransaction(
                'Receiver address is not of a Token type.')

        LOGGER.info("1. Ensure transaction initiated within an hour")
        # 1. Ensure transaction initiated within an hour
        swap_info.secret_lock = swap_init_payload.secret_lock_by_solicitor
        created_at = self.get_datetime_from_timestamp(swap_info.created_at)
        now = datetime.datetime.utcnow()

        if not (now - datetime.timedelta(hours=1) < created_at < now):
            raise InvalidTransaction(
                'Transaction is created a long time ago or timestamp is assigned set.'
            )
        # END

        LOGGER.info("2. Check weather the sender is Alice")
        # 2. Check weather the sender is Alice:
        swap_info.is_initiator = not swap_init_payload.secret_lock_by_solicitor
        # END

        # 3. Transfer funds to zero address.
        LOGGER.info("3. Transfer funds to zero address")
        commission = int(_get_setting_value(context, SETTINGS_SWAP_COMMISSION))
        if commission < 0:
            raise InvalidTransaction('Wrong commission address.')
        LOGGER.info("4. Get sender's account {}".format(
            swap_info.sender_address))
        account = get_account_by_address(context, swap_info.sender_address)
        total_amount = swap_info.amount + commission
        if account.balance < total_amount:
            raise InvalidTransaction(
                'Not enough balance to perform the transaction in '
                'the amount (with a commission) {}.'.format(total_amount))

        transfer_payload = AccountClient.get_transfer_payload(
            ZERO_ADDRESS, total_amount)
        token_updated_state = AccountHandler()._transfer_from_address(
            context, swap_info.sender_address, transfer_payload)
        LOGGER.info("Save state")

        return {**self.get_state_update(swap_info), **token_updated_state}