137 lines
4.5 KiB
Python
137 lines
4.5 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
|
||
|
|
from yuxi.channels.adapters.nostr.zap import NostrZapManager
|
||
|
|
|
||
|
|
|
||
|
|
class TestNostrZapManager:
|
||
|
|
@pytest.fixture
|
||
|
|
def crypto(self):
|
||
|
|
crypto = MagicMock()
|
||
|
|
crypto.build_and_sign_event.return_value = {
|
||
|
|
"id": "zap_event_id",
|
||
|
|
"kind": 9734,
|
||
|
|
"content": "",
|
||
|
|
"tags": [["p", "receiver_hex"], ["amount", "1000"]],
|
||
|
|
}
|
||
|
|
return crypto
|
||
|
|
|
||
|
|
@pytest.fixture
|
||
|
|
def relay_manager(self):
|
||
|
|
rm = MagicMock()
|
||
|
|
rm.broadcast = AsyncMock(return_value=3)
|
||
|
|
return rm
|
||
|
|
|
||
|
|
@pytest.fixture
|
||
|
|
def zap_manager(self, crypto, relay_manager):
|
||
|
|
return NostrZapManager(crypto, relay_manager)
|
||
|
|
|
||
|
|
def test_parse_zap_receipt_valid(self, zap_manager):
|
||
|
|
raw_event = {
|
||
|
|
"id": "zap_receipt_001",
|
||
|
|
"kind": 9735,
|
||
|
|
"pubkey": "sender_pubkey_hex",
|
||
|
|
"tags": [
|
||
|
|
["bolt11", "lnbc1invoice"],
|
||
|
|
["amount", "5000000"],
|
||
|
|
["p", "receiver_pubkey_hex"],
|
||
|
|
["e", "event_id_001"],
|
||
|
|
],
|
||
|
|
}
|
||
|
|
result = zap_manager.parse_zap_receipt(raw_event)
|
||
|
|
assert result is not None
|
||
|
|
assert result["event_id"] == "zap_receipt_001"
|
||
|
|
assert result["sender_pubkey"] == "sender_pubkey_hex"
|
||
|
|
assert result["amount_msat"] == 5000000
|
||
|
|
assert result["amount_sats"] == 5000
|
||
|
|
assert result["bolt11"] == "lnbc1invoice"
|
||
|
|
assert result["zapped_pubkey"] == "receiver_pubkey_hex"
|
||
|
|
assert result["zapped_event_id"] == "event_id_001"
|
||
|
|
|
||
|
|
def test_parse_zap_receipt_wrong_kind(self, zap_manager):
|
||
|
|
raw_event = {
|
||
|
|
"id": "not_a_zap",
|
||
|
|
"kind": 1,
|
||
|
|
"pubkey": "sender_hex",
|
||
|
|
"tags": [],
|
||
|
|
}
|
||
|
|
result = zap_manager.parse_zap_receipt(raw_event)
|
||
|
|
assert result is None
|
||
|
|
|
||
|
|
def test_parse_zap_receipt_minimal(self, zap_manager):
|
||
|
|
raw_event = {
|
||
|
|
"id": "minimal_zap",
|
||
|
|
"kind": 9735,
|
||
|
|
"pubkey": "sender_hex",
|
||
|
|
"tags": [],
|
||
|
|
}
|
||
|
|
result = zap_manager.parse_zap_receipt(raw_event)
|
||
|
|
assert result is not None
|
||
|
|
assert result["amount_msat"] == 0
|
||
|
|
assert result["amount_sats"] == 0
|
||
|
|
assert result["bolt11"] == ""
|
||
|
|
|
||
|
|
def test_parse_zap_receipt_invalid_amount(self, zap_manager):
|
||
|
|
raw_event = {
|
||
|
|
"id": "bad_amount_zap",
|
||
|
|
"kind": 9735,
|
||
|
|
"pubkey": "sender_hex",
|
||
|
|
"tags": [
|
||
|
|
["amount", "not_a_number"],
|
||
|
|
],
|
||
|
|
}
|
||
|
|
result = zap_manager.parse_zap_receipt(raw_event)
|
||
|
|
assert result is not None
|
||
|
|
assert result["amount_msat"] == 0
|
||
|
|
|
||
|
|
def test_parse_zap_receipt_missing_tags(self, zap_manager):
|
||
|
|
raw_event = {
|
||
|
|
"id": "no_tags_zap",
|
||
|
|
"kind": 9735,
|
||
|
|
"pubkey": "sender_hex",
|
||
|
|
}
|
||
|
|
result = zap_manager.parse_zap_receipt(raw_event)
|
||
|
|
assert result is not None
|
||
|
|
assert result["amount_msat"] == 0
|
||
|
|
|
||
|
|
def test_parse_zap_receipt_empty_tags_list(self, zap_manager):
|
||
|
|
raw_event = {
|
||
|
|
"id": "zap_empty",
|
||
|
|
"kind": 9735,
|
||
|
|
"pubkey": "sender_hex",
|
||
|
|
"tags": [[]],
|
||
|
|
}
|
||
|
|
result = zap_manager.parse_zap_receipt(raw_event)
|
||
|
|
assert result is not None
|
||
|
|
|
||
|
|
def test_build_zap_request_basic(self, zap_manager):
|
||
|
|
event = zap_manager.build_zap_request("receiver_hex")
|
||
|
|
assert event is not None
|
||
|
|
assert event["kind"] == 9734
|
||
|
|
assert event["content"] == ""
|
||
|
|
|
||
|
|
def test_build_zap_request_with_event_id(self, zap_manager):
|
||
|
|
event = zap_manager.build_zap_request("receiver_hex", event_id="evt_001")
|
||
|
|
assert event is not None
|
||
|
|
|
||
|
|
def test_build_zap_request_with_amount(self, zap_manager):
|
||
|
|
event = zap_manager.build_zap_request("receiver_hex", amount_msat=21000)
|
||
|
|
assert event is not None
|
||
|
|
|
||
|
|
def test_build_zap_request_full(self, zap_manager):
|
||
|
|
event = zap_manager.build_zap_request("receiver_hex", "evt_001", 42000)
|
||
|
|
assert event["kind"] == 9734
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_broadcast_zap_request_success(self, zap_manager):
|
||
|
|
count = await zap_manager.broadcast_zap_request("receiver_hex", "evt_001", 1000)
|
||
|
|
assert count == 3
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_broadcast_zap_request_zero_relays(self, zap_manager):
|
||
|
|
zap_manager._relay_manager.broadcast = AsyncMock(return_value=0)
|
||
|
|
count = await zap_manager.broadcast_zap_request("receiver_hex")
|
||
|
|
assert count == 0
|