def test_sendSend(self):
     msgIn = messages.BL4PSend(
         localOrderID=0,
         amount=1234,
         paymentHash=b'foobar',
         max_locked_timeout_delta_s=5000,
         selfReport={'foo': 'bar'},
     )
     expectedMsgOut = bl4p_pb2.BL4P_Send()
     expectedMsgOut.sender_amount.amount = 1234
     expectedMsgOut.payment_hash.data = b'foobar'
     expectedMsgOut.max_locked_timeout_delta_s = 5000
     expectedMsgOut.report = selfreport.serialize({'foo': 'bar'})
     expectedMsgOut.signature = b'ecdsa_serialize:ecdsa_sign:' + expectedMsgOut.report
     self.doSingleSendTest(msgIn, expectedMsgOut)
Exemple #2
0
    async def sendFundsOnBL4P(self) -> None:
        assert isinstance(self.order, BuyOrder)
        assert isinstance(self.transaction, BuyTransaction)
        await self.waitForBL4PConnection()

        try:
            #Lock fiat funds:
            sendResult = cast(messages.BL4PSendResult,
             await self.call(messages.BL4PSend(
              localOrderID = self.order.ID,

              amount                     = self.transaction.fiatAmount,
              paymentHash                = self.transaction.paymentHash,
              max_locked_timeout_delta_s = self.order.getConditionMax(offer.Condition.LOCKED_TIMEOUT),
              selfReport                 = \
               {
               'paymentHash'         : self.transaction.paymentHash.hex(),
               'offerID'             : str(self.order.ID),
               'receiverCryptoAmount': formatCryptoAmount(self.transaction.cryptoAmount),
               'cryptoCurrency'      : self.order.ask.currency,
               },
              ),
              messages.BL4PSendResult)
             ) #type: messages.BL4PSendResult
        except BL4PError:
            logging.error('Error received from BL4P - transaction canceled')
            self.order.setAmount(self.order.amount +
                                 self.transaction.fiatAmount)
            self.transaction.update(status=TX_STATUS_CANCELED, )
            await self.cancelTransactionOnLightning()
            return

        #TODO: what if this asserion fails?
        assert sha256(
            sendResult.paymentPreimage) == self.transaction.paymentHash
        logging.info('We got the preimage from BL4P')

        self.transaction.update(
            paymentPreimage=sendResult.paymentPreimage,
            status=TX_STATUS_FINISHED,
        )

        await self.finishTransactionOnLightning()
Exemple #3
0
    async def test_failedBuyTransaction(self):
        orderID = ordertask.BuyOrder.create(
            self.storage,
            190000,  #mCent / BTC = 1.9 EUR/BTC
            123400000  #mCent    = 1234 EUR
        )
        order = ordertask.BuyOrder(self.storage, orderID, 'buyerAddress')
        order.remoteOfferID = 6
        order.setAmount = Mock()

        self.storage.buyTransactions = \
        {
        41:
         {
         'ID': 41,
         'buyOrder': orderID,
         'status': 0,
         'fiatAmount': 100000000,
         'cryptoAmount': 200000000,
         'paymentHash': b'foo',
         }
        }

        task = ordertask.OrderTask(self.client, self.storage, order)
        task.startup()

        await asyncio.sleep(0.1)

        task.setCallResult(
            messages.LNIncoming(
                offerID=42,
                CLTVExpiryDelta=0,
                fiatAmount=100000000,
                cryptoAmount=200000000,
                paymentHash=b'foo',
            ))

        msg = await self.outgoingMessages.get()
        self.assertEqual(msg, messages.BL4PSend(
         localOrderID=42,

         amount = 100000000,
         paymentHash = b'foo',
         max_locked_timeout_delta_s = 3600*24*14,
         selfReport = \
          {
          'paymentHash'         : '666f6f', #foo in hex
          'offerID'             : str(orderID),
          'receiverCryptoAmount': '0.00200000000',
          'cryptoCurrency'      : 'btc',
          },
         ))
        task.setCallResult(messages.BL4PError(request=None, ))

        #LN transaction gets canceled
        msg = await self.outgoingMessages.get()
        self.assertEqual(msg, messages.LNFail(paymentHash=b'foo', ))

        order.setAmount.assert_called_once_with(223400000)
        self.assertEqual(
            self.storage.buyTransactions, {
                41: {
                    'ID': 41,
                    'status': ordertask.TX_STATUS_CANCELED,
                    'buyOrder': orderID,
                    'fiatAmount': 100000000,
                    'cryptoAmount': 200000000,
                    'paymentHash': b'foo',
                }
            })
        self.assertEqual(task.transaction, None)

        #Old offer gets removed
        msg = await self.outgoingMessages.get()
        self.assertTrue(isinstance(msg, messages.BL4PRemoveOffer))
        task.setCallResult(messages.BL4PRemoveOfferResult(request=None, ))

        #New offer gets added
        msg = await self.outgoingMessages.get()
        self.assertTrue(isinstance(msg, messages.BL4PAddOffer))
        task.setCallResult(messages.BL4PAddOfferResult(
            request=None,
            ID=6,
        ))

        #Continues to next iteration:
        await asyncio.sleep(0.1)

        await self.shutdownOrderTask(task)
Exemple #4
0
    async def test_continueBuyTransaction(self):
        orderID = ordertask.BuyOrder.create(
            self.storage,
            190000,  #mCent / BTC = 1.9 EUR/BTC
            123400000  #mCent    = 1234 EUR
        )
        order = ordertask.BuyOrder(self.storage, orderID, 'buyerAddress')

        self.storage.buyTransactions = \
        {
        41:
         {
         'ID': 41,
         'buyOrder': orderID,
         'status': 0,

         'fiatAmount': 100000000,
         'cryptoAmount': 200000000,

         'paymentHash': b'foo',
         }
        }

        task = ordertask.OrderTask(self.client, self.storage, order)
        task.startup()

        await asyncio.sleep(0.1)

        task.setCallResult(
            messages.LNIncoming(
                offerID=42,
                CLTVExpiryDelta=0,
                fiatAmount=100000000,
                cryptoAmount=200000000,
                paymentHash=b'foo',
            ))

        msg = await self.outgoingMessages.get()
        self.assertEqual(msg, messages.BL4PSend(
         localOrderID=42,

         amount = 100000000,
         paymentHash = b'foo',
         max_locked_timeout_delta_s = 3600*24*14,
         selfReport = \
          {
          'paymentHash'         : '666f6f', #foo in hex
          'offerID'             : str(orderID),
          'receiverCryptoAmount': '0.00200000000',
          'cryptoCurrency'      : 'btc',
          },
         ))

        await task.shutdown()

        #Database inconsistency exception:
        self.storage.buyTransactions = \
        {
        41:
         {
         'ID': 41,
         'buyOrder': orderID,
         'status': 100,
         }
        }

        task = ordertask.OrderTask(self.client, self.storage, order)
        with self.assertRaises(Exception):
            await task.continueBuyTransaction()
Exemple #5
0
    async def test_buyer_goodFlow(self):
        orderID = ordertask.BuyOrder.create(
            self.storage,
            190000,  #mCent / BTC = 1.9 EUR/BTC
            123400000  #mCent    = 1234 EUR
        )
        order = ordertask.BuyOrder(self.storage, orderID, 'lnAddress')

        task = ordertask.OrderTask(self.client, self.storage, order)
        task.startup()

        remainingAmount = order.amount
        for txAmount in [100000000, 23400000]:
            self.storage.reset(
                startCount=43)  #clean up from previous iteration
            self.storage.buyOrders[orderID] = {}
            order.setAmount = Mock()  #Replace mock object with a fresh one

            #Offer gets published
            msg = await self.outgoingMessages.get()
            self.assertEqual(
                msg, messages.BL4PAddOffer(
                    localOrderID=42,
                    offer=order,
                ))
            task.setCallResult(
                messages.BL4PAddOfferResult(
                    request=None,
                    ID=6,
                ))

            #TODO: is the next message in a race condition with the previous?
            await asyncio.sleep(0.1)

            #Incoming LN transaction arrives
            paymentPreimage = b'foo'
            paymentHash = sha256(paymentPreimage)
            task.setCallResult(
                messages.LNIncoming(
                    offerID=42,
                    CLTVExpiryDelta=0,
                    fiatAmount=txAmount,
                    cryptoAmount=100000000000000,
                    paymentHash=paymentHash,
                ))

            msg = await self.outgoingMessages.get()

            remainingAmount -= txAmount
            order.setAmount.assert_called_once_with(remainingAmount)
            order.amount = remainingAmount
            self.assertEqual(
                self.storage.buyTransactions, {
                    43: {
                        'ID': 43,
                        'status': ordertask.TX_STATUS_INITIAL,
                        'buyOrder': 42,
                        'fiatAmount': txAmount,
                        'cryptoAmount': 100000000000000,
                        'paymentHash': paymentHash,
                        'paymentPreimage': None,
                    }
                })

            #Funds get sent on BL4P
            self.assertEqual(msg, messages.BL4PSend(
             localOrderID=42,

             amount=txAmount,
             paymentHash=paymentHash,
             max_locked_timeout_delta_s = 3600*24*14,
             selfReport = \
              {
              'paymentHash'         : paymentHash.hex(),
              'offerID'             : str(orderID),
              'receiverCryptoAmount': '1000.00000000000',
              'cryptoCurrency'      : 'btc',
              },
             ))
            task.setCallResult(
                messages.BL4PSendResult(
                    request=None,
                    paymentPreimage=paymentPreimage,
                ))

            msg = await self.outgoingMessages.get()

            self.assertEqual(
                self.storage.buyTransactions, {
                    43: {
                        'ID': 43,
                        'status': ordertask.TX_STATUS_FINISHED,
                        'buyOrder': 42,
                        'fiatAmount': txAmount,
                        'cryptoAmount': 100000000000000,
                        'paymentHash': paymentHash,
                        'paymentPreimage': paymentPreimage,
                    }
                })
            self.assertEqual(task.transaction, None)

            #LN transaction gets finished
            self.assertEqual(
                msg,
                messages.LNFinish(
                    paymentHash=paymentHash,
                    paymentPreimage=paymentPreimage,
                ))

            #Old offer gets removed
            msg = await self.outgoingMessages.get()
            self.assertEqual(
                msg, messages.BL4PRemoveOffer(
                    localOrderID=42,
                    offerID=6,
                ))
            task.setCallResult(messages.BL4PRemoveOfferResult(request=None, ))

        await task.waitFinished()

        self.assertEqual(self.storage.buyOrders[orderID]['status'],
                         1)  #completed