mirror of
https://github.com/basicswap/basicswap.git
synced 2025-11-06 02:38:11 +01:00
Support xmr-protocol swaps to BTC and PART
This commit is contained in:
@@ -28,6 +28,8 @@ from tests.basicswap.util import (
|
||||
from tests.basicswap.common import (
|
||||
wait_for_bid,
|
||||
wait_for_offer,
|
||||
wait_for_balance,
|
||||
wait_for_unspent,
|
||||
wait_for_none_active,
|
||||
BTC_BASE_RPC_PORT,
|
||||
)
|
||||
@@ -52,8 +54,8 @@ logger = logging.getLogger()
|
||||
class BasicSwapTest(BaseTest):
|
||||
base_rpc_port = None
|
||||
|
||||
def getBalance(self, js_wallets):
|
||||
return float(js_wallets[self.test_coin_from.name]['balance']) + float(js_wallets[self.test_coin_from.name]['unconfirmed'])
|
||||
def getBalance(self, js_wallets, coin):
|
||||
return float(js_wallets[coin.name]['balance']) + float(js_wallets[coin.name]['unconfirmed'])
|
||||
|
||||
def callnoderpc(self, method, params=[], wallet=None, node_id=0):
|
||||
return callnoderpc(node_id, method, params, wallet, self.base_rpc_port)
|
||||
@@ -252,22 +254,25 @@ class BasicSwapTest(BaseTest):
|
||||
self.callnoderpc('unloadwallet', [new_wallet_name])
|
||||
assert (addr == 'bcrt1qps7hnjd866e9ynxadgseprkc2l56m00dvwargr')
|
||||
|
||||
def test_01_full_swap(self):
|
||||
logging.info('---------- Test {} to XMR'.format(self.test_coin_from.name))
|
||||
def do_test_01_full_swap(self, coin_from, coin_to):
|
||||
logging.info('---------- Test {} to {}'.format(coin_from.name, coin_to.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[1].ci(coin_to)
|
||||
|
||||
js_0 = read_json_api(1800, 'wallets')
|
||||
node0_from_before = self.getBalance(js_0)
|
||||
node0_from_before = self.getBalance(js_0, coin_from)
|
||||
|
||||
js_1 = read_json_api(1801, 'wallets')
|
||||
node1_from_before = self.getBalance(js_1)
|
||||
node1_from_before = self.getBalance(js_1, coin_from)
|
||||
|
||||
js_0_xmr = read_json_api(1800, 'wallets/xmr')
|
||||
js_1_xmr = read_json_api(1801, 'wallets/xmr')
|
||||
js_0_to = read_json_api(1800, 'wallets/{}'.format(coin_to.name.lower()))
|
||||
js_1_to = read_json_api(1801, 'wallets/{}'.format(coin_to.name.lower()))
|
||||
|
||||
amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
|
||||
rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1)
|
||||
offer_id = swap_clients[0].postOffer(self.test_coin_from, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP)
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
offer_id = swap_clients[0].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP)
|
||||
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
|
||||
offers = swap_clients[0].listOffers(filters={'offer_id': offer_id})
|
||||
offer = offers[0]
|
||||
@@ -281,37 +286,55 @@ class BasicSwapTest(BaseTest):
|
||||
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
|
||||
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True)
|
||||
|
||||
amount_from = float(format_amount(amt_swap, 8))
|
||||
amount_from = float(ci_from.format_amount(amt_swap))
|
||||
js_1 = read_json_api(1801, 'wallets')
|
||||
node1_from_after = self.getBalance(js_1)
|
||||
assert (node1_from_after > node1_from_before + (amount_from - 0.05))
|
||||
node1_from_after = self.getBalance(js_1, coin_from)
|
||||
if coin_from is not Coins.PART: # TODO: staking
|
||||
assert (node1_from_after > node1_from_before + (amount_from - 0.05))
|
||||
|
||||
js_0 = read_json_api(1800, 'wallets')
|
||||
node0_from_after = self.getBalance(js_0)
|
||||
node0_from_after = self.getBalance(js_0, coin_from)
|
||||
# TODO: Discard block rewards
|
||||
# assert (node0_from_after < node0_from_before - amount_from)
|
||||
|
||||
js_0_xmr_after = read_json_api(1800, 'wallets/xmr')
|
||||
js_1_xmr_after = read_json_api(1801, 'wallets/xmr')
|
||||
js_0_to_after = read_json_api(1800, 'wallets/{}'.format(coin_to.name.lower()))
|
||||
js_1_to_after = read_json_api(1801, 'wallets/{}'.format(coin_to.name.lower()))
|
||||
|
||||
scale_from = 8
|
||||
amount_to = int((amt_swap * rate_swap) // (10 ** scale_from))
|
||||
amount_to_float = float(format_amount(amount_to, 12))
|
||||
node1_xmr_after = float(js_1_xmr_after['unconfirmed']) + float(js_1_xmr_after['balance'])
|
||||
node1_xmr_before = float(js_1_xmr['unconfirmed']) + float(js_1_xmr['balance'])
|
||||
assert (node1_xmr_after > node1_xmr_before + (amount_to_float - 0.02))
|
||||
amount_to_float = float(ci_to.format_amount(amount_to))
|
||||
node1_to_after = float(js_1_to_after['unconfirmed']) + float(js_1_to_after['balance'])
|
||||
node1_to_before = float(js_1_to['unconfirmed']) + float(js_1_to['balance'])
|
||||
if False: # TODO: set stakeaddress and xmr rewards to non wallet addresses
|
||||
assert (node1_to_after < node1_to_before - amount_to_float)
|
||||
|
||||
def test_01_full_swap(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.do_test_01_full_swap(self.test_coin_from, Coins.XMR)
|
||||
|
||||
def test_01_full_swap_to_part(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.do_test_01_full_swap(self.test_coin_from, Coins.PART)
|
||||
|
||||
def test_01_full_swap_from_part(self):
|
||||
self.do_test_01_full_swap(Coins.PART, self.test_coin_from)
|
||||
|
||||
def do_test_02_leader_recover_a_lock_tx(self, coin_from, coin_to):
|
||||
logging.info('---------- Test {} to {} leader recovers coin a lock tx'.format(coin_from.name, coin_to.name))
|
||||
|
||||
def test_02_leader_recover_a_lock_tx(self):
|
||||
logging.info('---------- Test {} to XMR leader recovers coin a lock tx'.format(self.test_coin_from.name))
|
||||
swap_clients = self.swap_clients
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
js_w0_before = read_json_api(1800, 'wallets')
|
||||
node0_from_before = self.getBalance(js_w0_before)
|
||||
node0_from_before = self.getBalance(js_w0_before, coin_from)
|
||||
|
||||
amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
|
||||
rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1)
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
offer_id = swap_clients[0].postOffer(
|
||||
self.test_coin_from, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
|
||||
coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
|
||||
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32)
|
||||
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
|
||||
offer = swap_clients[1].getOffer(offer_id)
|
||||
@@ -331,28 +354,43 @@ class BasicSwapTest(BaseTest):
|
||||
wait_for_bid(test_delay_event, swap_clients[1], bid_id, [BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED], sent=True)
|
||||
|
||||
js_w0_after = read_json_api(1800, 'wallets')
|
||||
node0_from_after = self.getBalance(js_w0_after)
|
||||
node0_from_after = self.getBalance(js_w0_after, coin_from)
|
||||
|
||||
# TODO: Discard block rewards
|
||||
# assert (node0_from_before - node0_from_after < 0.02)
|
||||
|
||||
def test_03_follower_recover_a_lock_tx(self):
|
||||
logging.info('---------- Test {} to XMR follower recovers coin a lock tx'.format(self.test_coin_from.name))
|
||||
def test_02_leader_recover_a_lock_tx(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.do_test_02_leader_recover_a_lock_tx(self.test_coin_from, Coins.XMR)
|
||||
|
||||
def test_02_leader_recover_a_lock_tx_to_part(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.do_test_02_leader_recover_a_lock_tx(self.test_coin_from, Coins.PART)
|
||||
|
||||
def test_02_leader_recover_a_lock_tx_from_part(self):
|
||||
self.do_test_02_leader_recover_a_lock_tx(Coins.PART, self.test_coin_from)
|
||||
|
||||
def do_test_03_follower_recover_a_lock_tx(self, coin_from, coin_to):
|
||||
logging.info('---------- Test {} to {} follower recovers coin a lock tx'.format(coin_from.name, coin_to.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
js_w0_before = read_json_api(1800, 'wallets')
|
||||
js_w1_before = read_json_api(1801, 'wallets')
|
||||
|
||||
amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
|
||||
rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1)
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
offer_id = swap_clients[0].postOffer(
|
||||
self.test_coin_from, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
|
||||
coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
|
||||
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32)
|
||||
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
|
||||
offer = swap_clients[1].getOffer(offer_id)
|
||||
|
||||
bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED)
|
||||
|
||||
bid, xmr_swap = swap_clients[0].getXmrBid(bid_id)
|
||||
@@ -368,8 +406,8 @@ class BasicSwapTest(BaseTest):
|
||||
|
||||
js_w1_after = read_json_api(1801, 'wallets')
|
||||
|
||||
node1_from_before = self.getBalance(js_w1_before)
|
||||
node1_from_after = self.getBalance(js_w1_after)
|
||||
node1_from_before = self.getBalance(js_w1_before, coin_from)
|
||||
node1_from_after = self.getBalance(js_w1_after, coin_from)
|
||||
amount_from = float(format_amount(amt_swap, 8))
|
||||
# TODO: Discard block rewards
|
||||
# assert (node1_from_after - node1_from_before > (amount_from - 0.02))
|
||||
@@ -379,24 +417,38 @@ class BasicSwapTest(BaseTest):
|
||||
wait_for_none_active(test_delay_event, 1800)
|
||||
wait_for_none_active(test_delay_event, 1801)
|
||||
|
||||
def test_04_follower_recover_b_lock_tx(self):
|
||||
logging.info('---------- Test {} to XMR follower recovers coin b lock tx'.format(self.test_coin_from.name))
|
||||
def test_03_follower_recover_a_lock_tx(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.do_test_03_follower_recover_a_lock_tx(self.test_coin_from, Coins.XMR)
|
||||
|
||||
def test_03_follower_recover_a_lock_tx_to_part(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.do_test_03_follower_recover_a_lock_tx(self.test_coin_from, Coins.PART)
|
||||
|
||||
def test_03_follower_recover_a_lock_tx_from_part(self):
|
||||
self.do_test_03_follower_recover_a_lock_tx(Coins.PART, self.test_coin_from)
|
||||
|
||||
def do_test_04_follower_recover_b_lock_tx(self, coin_from, coin_to):
|
||||
logging.info('---------- Test {} to {} follower recovers coin b lock tx'.format(coin_from.name, coin_to.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
js_w0_before = read_json_api(1800, 'wallets')
|
||||
js_w1_before = read_json_api(1801, 'wallets')
|
||||
|
||||
amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
|
||||
rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1)
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
offer_id = swap_clients[0].postOffer(
|
||||
self.test_coin_from, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
|
||||
coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
|
||||
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32)
|
||||
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
|
||||
offer = swap_clients[1].getOffer(offer_id)
|
||||
|
||||
bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED)
|
||||
|
||||
bid, xmr_swap = swap_clients[0].getXmrBid(bid_id)
|
||||
@@ -411,28 +463,127 @@ class BasicSwapTest(BaseTest):
|
||||
js_w0_after = read_json_api(1800, 'wallets')
|
||||
js_w1_after = read_json_api(1801, 'wallets')
|
||||
|
||||
node0_from_before = self.getBalance(js_w0_before)
|
||||
node0_from_after = self.getBalance(js_w0_after)
|
||||
|
||||
node0_from_before = self.getBalance(js_w0_before, coin_from)
|
||||
node0_from_after = self.getBalance(js_w0_after, coin_from)
|
||||
logging.info('End coin_from balance {}, diff {}'.format(node0_from_after, node0_from_after - node0_from_before))
|
||||
# TODO: Discard block rewards
|
||||
# assert (node0_from_before - node0_from_after < 0.02)
|
||||
|
||||
node1_xmr_before = self.getXmrBalance(js_w1_before)
|
||||
node1_xmr_after = self.getXmrBalance(js_w1_after)
|
||||
assert (node1_xmr_before - node1_xmr_after < 0.02)
|
||||
node1_coin_to_before = self.getBalance(js_w1_before, coin_to)
|
||||
node1_coin_to_after = self.getBalance(js_w1_after, coin_to)
|
||||
logging.info('End coin_to balance {}, diff {}'.format(node1_coin_to_after, node1_coin_to_after - node1_coin_to_before))
|
||||
assert (node1_coin_to_before - node1_coin_to_after < 0.02)
|
||||
|
||||
def test_04_follower_recover_b_lock_tx(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.do_test_04_follower_recover_b_lock_tx(self.test_coin_from, Coins.XMR)
|
||||
|
||||
def test_04_follower_recover_b_lock_tx_to_part(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.do_test_04_follower_recover_b_lock_tx(self.test_coin_from, Coins.PART)
|
||||
|
||||
def test_04_follower_recover_b_lock_tx_from_part(self):
|
||||
self.do_test_04_follower_recover_b_lock_tx(Coins.PART, self.test_coin_from)
|
||||
|
||||
def do_test_05_self_bid(self, coin_from, coin_to):
|
||||
logging.info('---------- Test {} to {} same client'.format(coin_from.name, coin_to.name))
|
||||
|
||||
def test_05_self_bid(self):
|
||||
logging.info('---------- Test {} to XMR same client'.format(self.test_coin_from.name))
|
||||
swap_clients = self.swap_clients
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
|
||||
rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
|
||||
offer_id = swap_clients[1].postOffer(self.test_coin_from, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, auto_accept_bids=True)
|
||||
offer_id = swap_clients[1].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, auto_accept_bids=True)
|
||||
bid_id = swap_clients[1].postXmrBid(offer_id, amt_swap)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
|
||||
|
||||
def test_05_self_bid(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.do_test_05_self_bid(self.test_coin_from, Coins.XMR)
|
||||
|
||||
def test_05_self_bid_to_part(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.do_test_05_self_bid(self.test_coin_from, Coins.PART)
|
||||
|
||||
def test_05_self_bid_from_part(self):
|
||||
self.do_test_05_self_bid(Coins.PART, self.test_coin_from)
|
||||
|
||||
def test_06_preselect_inputs(self):
|
||||
tla_from = self.test_coin_from.name
|
||||
logging.info('---------- Test {} Preselected inputs'.format(tla_from))
|
||||
swap_clients = self.swap_clients
|
||||
|
||||
# Prepare balance
|
||||
js_w2 = read_json_api(1802, 'wallets')
|
||||
if float(js_w2[tla_from]['balance']) < 100.0:
|
||||
post_json = {
|
||||
'value': 100,
|
||||
'address': js_w2[tla_from]['deposit_address'],
|
||||
'subfee': False,
|
||||
}
|
||||
json_rv = read_json_api(1800, 'wallets/{}/withdraw'.format(tla_from.lower()), post_json)
|
||||
assert (len(json_rv['txid']) == 64)
|
||||
wait_for_balance(test_delay_event, 'http://127.0.0.1:1802/json/wallets/{}'.format(tla_from.lower()), 'balance', 100.0)
|
||||
|
||||
js_w2 = read_json_api(1802, 'wallets')
|
||||
assert (float(js_w2[tla_from]['balance']) >= 100.0)
|
||||
|
||||
js_w2 = read_json_api(1802, 'wallets')
|
||||
post_json = {
|
||||
'value': float(js_w2[tla_from]['balance']),
|
||||
'address': read_json_api(1802, 'wallets/{}/nextdepositaddr'.format(tla_from.lower())),
|
||||
'subfee': True,
|
||||
}
|
||||
json_rv = read_json_api(1802, 'wallets/{}/withdraw'.format(tla_from.lower()), post_json)
|
||||
wait_for_balance(test_delay_event, 'http://127.0.0.1:1802/json/wallets/{}'.format(tla_from.lower()), 'balance', 10.0)
|
||||
assert (len(json_rv['txid']) == 64)
|
||||
|
||||
# Create prefunded ITX
|
||||
ci = swap_clients[2].ci(self.test_coin_from)
|
||||
ci_to = swap_clients[2].ci(Coins.XMR)
|
||||
pi = swap_clients[2].pi(SwapTypes.XMR_SWAP)
|
||||
js_w2 = read_json_api(1802, 'wallets')
|
||||
swap_value = ci.make_int(js_w2[tla_from]['balance'])
|
||||
assert (swap_value > ci.make_int(95))
|
||||
|
||||
itx = pi.getFundedInitiateTxTemplate(ci, swap_value, True)
|
||||
itx_decoded = ci.describeTx(itx.hex())
|
||||
value_after_subfee = ci.make_int(itx_decoded['vout'][0]['value'])
|
||||
assert (value_after_subfee < swap_value)
|
||||
swap_value = value_after_subfee
|
||||
wait_for_unspent(test_delay_event, ci, swap_value)
|
||||
|
||||
extra_options = {'prefunded_itx': itx}
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0))
|
||||
offer_id = swap_clients[2].postOffer(self.test_coin_from, Coins.XMR, swap_value, rate_swap, swap_value, SwapTypes.XMR_SWAP, extra_options=extra_options)
|
||||
|
||||
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
|
||||
offer = swap_clients[1].getOffer(offer_id)
|
||||
bid_id = swap_clients[1].postBid(offer_id, offer.amount_from)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.BID_RECEIVED)
|
||||
swap_clients[2].acceptBid(bid_id)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.SWAP_COMPLETED, wait_for=120)
|
||||
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120)
|
||||
|
||||
# Verify expected inputs were used
|
||||
bid, _, _, _, _ = swap_clients[2].getXmrBidAndOffer(bid_id)
|
||||
assert (bid.xmr_a_lock_tx)
|
||||
wtx = ci.rpc_callback('gettransaction', [bid.xmr_a_lock_tx.txid.hex(),])
|
||||
itx_after = ci.describeTx(wtx['hex'])
|
||||
assert (len(itx_after['vin']) == len(itx_decoded['vin']))
|
||||
for i, txin in enumerate(itx_decoded['vin']):
|
||||
txin_after = itx_after['vin'][i]
|
||||
assert (txin['txid'] == txin_after['txid'])
|
||||
assert (txin['vout'] == txin_after['vout'])
|
||||
|
||||
|
||||
class TestBTC(BasicSwapTest):
|
||||
__test__ = True
|
||||
|
||||
Reference in New Issue
Block a user