Add LN payout test

This commit is contained in:
Reckless_Satoshi
2023-11-17 15:16:03 +00:00
committed by Reckless_Satoshi
parent 1236829fcf
commit b2a130afca
4 changed files with 76 additions and 7 deletions

View File

@ -87,7 +87,7 @@ class LNDNode:
log("verstub.GetVersion", request, response) log("verstub.GetVersion", request, response)
return "v" + response.version return "v" + response.version
except Exception as e: except Exception as e:
print(f"Cannot get CLN version: {e}") print(f"Cannot get LND version: {e}")
return "Not installed" return "Not installed"
@classmethod @classmethod

View File

@ -175,6 +175,32 @@ services:
POSTGRES_DB: 'postgres' POSTGRES_DB: 'postgres'
network_mode: service:bitcoind network_mode: service:bitcoind
# celery-worker:
# image: robosats-image
# pull_policy: never
# container_name: celery-worker
# restart: always
# environment:
# DEVELOPMENT: True
# TESTING: True
# USE_TOR: False
# MACAROON_PATH: 'data/chain/bitcoin/regtest/admin.macaroon'
# CLN_DIR: '/cln/regtest/'
# BITCOIND_RPCURL: 'http://127.0.0.1:18443'
# BITCOIND_RPCUSER: 'test'
# BITCOIND_RPCPASSWORD: 'test'
# SKIP_COLLECT_STATIC: "true"
# env_file:
# - ${ROBOSATS_ENVS_FILE}
# volumes:
# - .:/usr/src/robosats
# - lnd:/lnd
# - cln:/cln
# command: celery -A robosats worker --loglevel=INFO --concurrency 2 --max-tasks-per-child=4 --max-memory-per-child=200000
# depends_on:
# - redis
# network_mode: service:bitcoind
volumes: volumes:
redisdata: redisdata:
bitcoin: bitcoin:

View File

@ -26,3 +26,10 @@ class BaseAPITestCase(APITestCase):
if response.request["PATH_INFO"] not in skip_paths: if response.request["PATH_INFO"] not in skip_paths:
schema_tester.validate_response(response=response, **kwargs) schema_tester.validate_response(response=response, **kwargs)
def assertIsHash(self, s):
hex_chars = set("0123456789abcdefABCDEF")
self.assertTrue(
len(s) == 64 and all(c in hex_chars for c in s),
"The hash is not 64 hex characters",
)

View File

@ -2,6 +2,7 @@ import json
import random import random
from datetime import datetime from datetime import datetime
from decimal import Decimal from decimal import Decimal
from unittest.mock import patch
from decouple import config from decouple import config
from django.contrib.auth.models import User from django.contrib.auth.models import User
@ -9,7 +10,7 @@ from django.urls import reverse
from api.management.commands.follow_invoices import Command as FollowInvoices from api.management.commands.follow_invoices import Command as FollowInvoices
from api.models import Currency, Order from api.models import Currency, Order
from api.tasks import cache_market from api.tasks import cache_market, follow_send_payment
from control.models import BalanceLog from control.models import BalanceLog
from control.tasks import compute_node_balance from control.tasks import compute_node_balance
from tests.node_utils import ( from tests.node_utils import (
@ -356,12 +357,16 @@ class TradeTest(BaseAPITestCase):
# Cancel order to avoid leaving pending HTLCs after a successful test # Cancel order to avoid leaving pending HTLCs after a successful test
self.cancel_order(data["id"]) self.cancel_order(data["id"])
def check_for_locked_bonds(self): def follow_hold_invoices(self):
# A background thread checks every 5 second the status of invoices. We invoke directly during test. # A background thread checks every 5 second the status of invoices. We invoke directly during test.
# It will ask LND via gRPC. In our test, the request/response from LND is mocked, and it will return fake invoice status "ACCEPTED"
follow_invoices = FollowInvoices() follow_invoices = FollowInvoices()
follow_invoices.follow_hold_invoices() follow_invoices.follow_hold_invoices()
def send_payments(self):
# A background thread checks every 5 second whether there are outgoing payments. We invoke directly during test.
follow_invoices = FollowInvoices()
follow_invoices.send_payments()
def make_and_publish_order(self, maker_form, robot_index=1): def make_and_publish_order(self, maker_form, robot_index=1):
# Make an order # Make an order
order_made_response = self.make_order(maker_form, robot_index) order_made_response = self.make_order(maker_form, robot_index)
@ -375,7 +380,7 @@ class TradeTest(BaseAPITestCase):
pay_invoice("robot", invoice) pay_invoice("robot", invoice)
# Check for invoice locked (the mocked LND will return ACCEPTED) # Check for invoice locked (the mocked LND will return ACCEPTED)
self.check_for_locked_bonds() self.follow_hold_invoices()
# Get order # Get order
response = self.get_order(order_made_data["id"]) response = self.get_order(order_made_data["id"])
@ -509,7 +514,7 @@ class TradeTest(BaseAPITestCase):
pay_invoice("robot", invoice) pay_invoice("robot", invoice)
# Check for invoice locked (the mocked LND will return ACCEPTED) # Check for invoice locked (the mocked LND will return ACCEPTED)
self.check_for_locked_bonds() self.follow_hold_invoices()
# Get order # Get order
response = self.get_order(order_taken_data["id"], taker_index) response = self.get_order(order_taken_data["id"], taker_index)
@ -578,7 +583,7 @@ class TradeTest(BaseAPITestCase):
pay_invoice("robot", invoice) pay_invoice("robot", invoice)
# Check for invoice locked (the mocked LND will return ACCEPTED) # Check for invoice locked (the mocked LND will return ACCEPTED)
self.check_for_locked_bonds() self.follow_hold_invoices()
# Get order # Get order
response = self.get_order(locked_taker_response_data["id"], taker_index) response = self.get_order(locked_taker_response_data["id"], taker_index)
@ -814,3 +819,34 @@ class TradeTest(BaseAPITestCase):
self.assertFalse(data["maker_locked"]) self.assertFalse(data["maker_locked"])
self.assertFalse(data["taker_locked"]) self.assertFalse(data["taker_locked"])
self.assertFalse(data["escrow_locked"]) self.assertFalse(data["escrow_locked"])
@patch("api.tasks.follow_send_payment.delay", follow_send_payment)
def test_successful_LN(self):
"""
Tests a trade from order creation until Sats sent to buyer
"""
maker_index = 1
taker_index = 2
maker_form = self.maker_form_buy_with_range
take_amount = round(
random.uniform(maker_form["min_amount"], maker_form["max_amount"]), 2
)
response = self.trade_to_confirm_fiat_received_LN(
maker_form, take_amount, maker_index, taker_index
)
# Invoke the background thread that will call the celery-worker to follow_send_payment()
self.send_payments()
response = self.get_order(response.json()["id"], maker_index)
data = response.json()
self.assertEqual(response.status_code, 200)
self.assertResponse(response)
self.assertEqual(data["status_message"], Order.Status(Order.Status.SUC).label)
self.assertTrue(data["is_fiat_sent"])
self.assertFalse(data["is_disputed"])
self.assertIsHash(data["maker_summary"]["preimage"])
self.assertIsHash(data["maker_summary"]["payment_hash"])