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)
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()
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)
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()
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