lnurl: implement LNURL-withdraw
adds handling of lnurl-withdraw payment identifiers which allow users to withdraw bitcoin from a service by scanning a qr code or pasting the lnurl-w code as "sending" address.
This commit is contained in:
@@ -20,3 +20,85 @@ class TestLnurl(TestCase):
|
||||
def test_lightning_address_to_url(self):
|
||||
url = lnurl.lightning_address_to_url("mempool@jhoenicke.de")
|
||||
self.assertEqual("https://jhoenicke.de/.well-known/lnurlp/mempool", url)
|
||||
|
||||
def test_parse_lnurl3_response(self):
|
||||
# Test successful parsing with all fields
|
||||
sample_response = {
|
||||
'callback': 'https://service.io/withdraw?sessionid=123',
|
||||
'k1': 'abcdef1234567890',
|
||||
'defaultDescription': 'Withdraw from service',
|
||||
'minWithdrawable': 10_000_000,
|
||||
'maxWithdrawable': 100_000_000,
|
||||
}
|
||||
|
||||
result = lnurl._parse_lnurl3_response(sample_response)
|
||||
|
||||
self.assertEqual('https://service.io/withdraw?sessionid=123', result.callback_url)
|
||||
self.assertEqual('abcdef1234567890', result.k1)
|
||||
self.assertEqual('Withdraw from service', result.default_description)
|
||||
self.assertEqual(10_000, result.min_withdrawable_sat)
|
||||
self.assertEqual(100_000, result.max_withdrawable_sat)
|
||||
|
||||
# Test with .onion URL
|
||||
onion_response = {
|
||||
'callback': 'http://robosatsy56bwqn56qyadmcxkx767hnabg4mihxlmgyt6if5gnuxvzad.onion/withdraw?sessionid=123',
|
||||
'k1': 'abcdef1234567890',
|
||||
'minWithdrawable': 10_000_000,
|
||||
'maxWithdrawable': 100_000_000
|
||||
}
|
||||
|
||||
result = lnurl._parse_lnurl3_response(onion_response)
|
||||
self.assertEqual('http://robosatsy56bwqn56qyadmcxkx767hnabg4mihxlmgyt6if5gnuxvzad.onion/withdraw?sessionid=123',
|
||||
result.callback_url)
|
||||
self.assertEqual('', result.default_description) # Missing defaultDescription uses empty string
|
||||
|
||||
# Test missing callback (should raise error)
|
||||
no_callback_response = {
|
||||
'k1': 'abcdef1234567890',
|
||||
'minWithdrawable': 10_000_000,
|
||||
'maxWithdrawable': 100_000_000
|
||||
}
|
||||
|
||||
with self.assertRaises(lnurl.LNURLError):
|
||||
lnurl._parse_lnurl3_response(no_callback_response)
|
||||
|
||||
# Test unsafe callback URL
|
||||
unsafe_response = {
|
||||
'callback': 'http://service.io/withdraw?sessionid=123', # HTTP URL
|
||||
'k1': 'abcdef1234567890',
|
||||
'minWithdrawable': 10_000_000,
|
||||
'maxWithdrawable': 100_000_000
|
||||
}
|
||||
|
||||
with self.assertRaises(lnurl.LNURLError):
|
||||
lnurl._parse_lnurl3_response(unsafe_response)
|
||||
|
||||
# Test missing k1 (should raise error)
|
||||
no_k1_response = {
|
||||
'callback': 'https://service.io/withdraw?sessionid=123',
|
||||
'minWithdrawable': 10_000_000,
|
||||
'maxWithdrawable': 100_000_000
|
||||
}
|
||||
|
||||
with self.assertRaises(lnurl.LNURLError):
|
||||
lnurl._parse_lnurl3_response(no_k1_response)
|
||||
|
||||
# Test missing withdrawable amounts (should raise error)
|
||||
no_amounts_response = {
|
||||
'callback': 'https://service.io/withdraw?sessionid=123',
|
||||
'k1': 'abcdef1234567890',
|
||||
}
|
||||
|
||||
with self.assertRaises(lnurl.LNURLError):
|
||||
lnurl._parse_lnurl3_response(no_amounts_response)
|
||||
|
||||
# Test malformed withdrawable amounts (should raise error)
|
||||
bad_amounts_response = {
|
||||
'callback': 'https://service.io/withdraw?sessionid=123',
|
||||
'k1': 'abcdef1234567890',
|
||||
'minWithdrawable': 'this is not a number',
|
||||
'maxWithdrawable': 100_000_000
|
||||
}
|
||||
|
||||
with self.assertRaises(lnurl.LNURLError):
|
||||
lnurl._parse_lnurl3_response(bad_amounts_response)
|
||||
|
||||
Reference in New Issue
Block a user