def test_handleHTLCAccepted_failed(self): self.interface.handleRequest( 6, 'htlc_accepted', { 'onion': { 'payload': '12fe424c34500cf1f2f3f4f5f6f7f8c1c2c3c4', }, 'htlc': { 'amount': '1234msat', 'cltv_expiry': 42, 'payment_hash': 'cafecafe', }, }) self.assertEqual(self.output.buffer, b'') self.client.handleIncomingMessage.assert_called_once_with( messages.LNIncoming( paymentHash=b'\xca\xfe\xca\xfe', cryptoAmount=1234, CLTVExpiryDelta=42, fiatAmount=0xf1f2f3f4f5f6f7f8, offerID=0xc1c2c3c4, )) self.interface.handleMessage( messages.LNFail(paymentHash=b'\xca\xfe\xca\xfe', )) self.checkJSONOutput({ 'jsonrpc': '2.0', 'id': 6, 'result': { 'result': 'fail', }, })
async def test_buyer_repeatFinishedTransaction(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': 4, #finished 'fiatAmount': 100000000, 'cryptoAmount': 200000000, 'paymentHash': b'foo', 'paymentPreimage': b'bar', }, 42: { 'ID': 42, 'buyOrder': orderID, 'status': 0, 'fiatAmount': 300000000, 'cryptoAmount': 600000000, 'paymentHash': b'foo2', } } 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.LNFinish(paymentHash=b'foo', paymentPreimage=b'bar')) await self.shutdownOrderTask(task)
async def test_refusedBuyTransaction(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() 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=100000000, #mCent = 1000 EUR cryptoAmount=50, #mBTC = 0.00000000050 BTC paymentHash=paymentHash, )) msg = await self.outgoingMessages.get() await self.shutdownOrderTask(task)
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