mirror of
https://github.com/basicswap/basicswap.git
synced 2024-11-16 15:58:17 +00:00
Add bid intent messages.
This commit is contained in:
parent
00bebfa371
commit
f6fb11f452
23 changed files with 1231 additions and 633 deletions
|
@ -17,8 +17,6 @@ import subprocess
|
|||
|
||||
from sockshandler import SocksiPyHandler
|
||||
|
||||
import basicswap.config as cfg
|
||||
|
||||
from .rpc import (
|
||||
callrpc,
|
||||
)
|
||||
|
@ -123,18 +121,6 @@ class BaseApp:
|
|||
cc = self.coin_clients[coin]
|
||||
return callrpc(cc['rpcport'], cc['rpcauth'], method, params, wallet, cc['rpchost'])
|
||||
|
||||
def calltx(self, cmd):
|
||||
bindir = self.coin_clients[Coins.PART]['bindir']
|
||||
args = [os.path.join(bindir, cfg.PARTICL_TX), ]
|
||||
if self.chain != 'mainnet':
|
||||
args.append('-' + self.chain)
|
||||
args += shlex.split(cmd)
|
||||
p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out = p.communicate()
|
||||
if len(out[1]) > 0:
|
||||
raise ValueError('TX error ' + str(out[1]))
|
||||
return out[0].decode('utf-8').strip()
|
||||
|
||||
def callcoincli(self, coin_type, params, wallet=None, timeout=None):
|
||||
bindir = self.coin_clients[coin_type]['bindir']
|
||||
datadir = self.coin_clients[coin_type]['datadir']
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -47,6 +47,9 @@ class MessageTypes(IntEnum):
|
|||
XMR_BID_LOCK_RELEASE_LF = auto()
|
||||
OFFER_REVOKE = auto()
|
||||
|
||||
ADS_BID_LF = auto()
|
||||
ADS_BID_ACCEPT_FL = auto()
|
||||
|
||||
|
||||
class AddressTypes(IntEnum):
|
||||
OFFER = auto()
|
||||
|
@ -98,6 +101,7 @@ class BidStates(IntEnum):
|
|||
BID_STATE_UNKNOWN = 26
|
||||
XMR_SWAP_MSG_SCRIPT_LOCK_TX_SIGS = 27 # XmrBidLockTxSigsMessage
|
||||
XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX = 28 # XmrBidLockSpendTxMessage
|
||||
BID_REQUEST_SENT = 29
|
||||
|
||||
|
||||
class TxStates(IntEnum):
|
||||
|
@ -140,6 +144,7 @@ class ActionTypes(IntEnum):
|
|||
RECOVER_XMR_SWAP_LOCK_TX_B = auto()
|
||||
SEND_XMR_SWAP_LOCK_SPEND_MSG = auto()
|
||||
REDEEM_ITX = auto()
|
||||
ACCEPT_AS_REV_BID = auto()
|
||||
|
||||
|
||||
class EventLogTypes(IntEnum):
|
||||
|
@ -296,6 +301,9 @@ def strBidState(state):
|
|||
return 'Exchanged script lock tx sigs msg'
|
||||
if state == BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX:
|
||||
return 'Exchanged script lock spend tx msg'
|
||||
if state == BidStates.BID_REQUEST_SENT:
|
||||
return 'Request sent'
|
||||
|
||||
return 'Unknown' + ' ' + str(state)
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ from enum import IntEnum, auto
|
|||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
||||
|
||||
CURRENT_DB_VERSION = 20
|
||||
CURRENT_DB_VERSION = 21
|
||||
CURRENT_DB_DATA_VERSION = 3
|
||||
Base = declarative_base()
|
||||
|
||||
|
@ -86,6 +86,7 @@ class Offer(Base):
|
|||
auto_accept_bids = sa.Column(sa.Boolean)
|
||||
withdraw_to_addr = sa.Column(sa.String) # Address to spend lock tx to - address from wallet if empty TODO
|
||||
security_token = sa.Column(sa.LargeBinary)
|
||||
bid_reversed = sa.Column(sa.Boolean)
|
||||
|
||||
state = sa.Column(sa.Integer)
|
||||
states = sa.Column(sa.LargeBinary) # Packed states and times
|
||||
|
@ -123,7 +124,6 @@ class Bid(Base):
|
|||
amount = sa.Column(sa.BigInteger)
|
||||
rate = sa.Column(sa.BigInteger)
|
||||
|
||||
accept_msg_id = sa.Column(sa.LargeBinary)
|
||||
pkhash_seller = sa.Column(sa.LargeBinary)
|
||||
|
||||
initiate_txn_redeem = sa.Column(sa.LargeBinary)
|
||||
|
@ -290,6 +290,7 @@ class EventLog(Base):
|
|||
|
||||
class XmrOffer(Base):
|
||||
__tablename__ = 'xmr_offers'
|
||||
# TODO: Merge to Offer
|
||||
|
||||
swap_id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
||||
offer_id = sa.Column(sa.LargeBinary, sa.ForeignKey('offers.offer_id'))
|
||||
|
@ -306,16 +307,6 @@ class XmrSwap(Base):
|
|||
|
||||
swap_id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
||||
bid_id = sa.Column(sa.LargeBinary, sa.ForeignKey('bids.bid_id'))
|
||||
bid_msg_id2 = sa.Column(sa.LargeBinary)
|
||||
bid_msg_id3 = sa.Column(sa.LargeBinary)
|
||||
|
||||
bid_accept_msg_id = sa.Column(sa.LargeBinary)
|
||||
bid_accept_msg_id2 = sa.Column(sa.LargeBinary)
|
||||
bid_accept_msg_id3 = sa.Column(sa.LargeBinary)
|
||||
|
||||
coin_a_lock_tx_sigs_l_msg_id = sa.Column(sa.LargeBinary) # MSG3L F -> L
|
||||
coin_a_lock_spend_tx_msg_id = sa.Column(sa.LargeBinary) # MSG4F L -> F
|
||||
coin_a_lock_release_msg_id = sa.Column(sa.LargeBinary) # MSG5F L -> F
|
||||
|
||||
contract_count = sa.Column(sa.Integer)
|
||||
|
||||
|
@ -503,3 +494,19 @@ class Notification(Base):
|
|||
created_at = sa.Column(sa.BigInteger)
|
||||
event_type = sa.Column(sa.Integer)
|
||||
event_data = sa.Column(sa.LargeBinary)
|
||||
|
||||
|
||||
class MessageLink(Base):
|
||||
__tablename__ = 'message_links'
|
||||
|
||||
record_id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
||||
active_ind = sa.Column(sa.Integer)
|
||||
created_at = sa.Column(sa.BigInteger)
|
||||
|
||||
linked_type = sa.Column(sa.Integer)
|
||||
linked_id = sa.Column(sa.LargeBinary)
|
||||
# linked_row_id = sa.Column(sa.Integer) # TODO: Find a way to use table rowids
|
||||
|
||||
msg_type = sa.Column(sa.Integer)
|
||||
msg_sequence = sa.Column(sa.Integer)
|
||||
msg_id = sa.Column(sa.LargeBinary)
|
||||
|
|
|
@ -266,6 +266,22 @@ def upgradeDatabase(self, db_version):
|
|||
session.execute('ALTER TABLE bidstates ADD COLUMN in_error INTEGER')
|
||||
session.execute('ALTER TABLE bidstates ADD COLUMN swap_failed INTEGER')
|
||||
session.execute('ALTER TABLE bidstates ADD COLUMN swap_ended INTEGER')
|
||||
elif current_version == 20:
|
||||
db_version += 1
|
||||
session.execute('''
|
||||
CREATE TABLE message_links (
|
||||
record_id INTEGER NOT NULL,
|
||||
active_ind INTEGER,
|
||||
created_at BIGINT,
|
||||
|
||||
linked_type INTEGER,
|
||||
linked_id BLOB,
|
||||
|
||||
msg_type INTEGER,
|
||||
msg_sequence INTEGER,
|
||||
msg_id BLOB,
|
||||
PRIMARY KEY (record_id))''')
|
||||
session.execute('ALTER TABLE offers ADD COLUMN bid_reversed INTEGER')
|
||||
|
||||
if current_version != db_version:
|
||||
self.db_version = db_version
|
||||
|
|
|
@ -38,6 +38,7 @@ def remove_expired_data(self):
|
|||
session.execute('DELETE FROM addresspool WHERE addresspool.bid_id = :bid_id', {'bid_id': bid_row[0]})
|
||||
session.execute('DELETE FROM xmr_split_data WHERE xmr_split_data.bid_id = :bid_id', {'bid_id': bid_row[0]})
|
||||
session.execute('DELETE FROM bids WHERE bids.bid_id = :bid_id', {'bid_id': bid_row[0]})
|
||||
session.execute('DELETE FROM message_links WHERE linked_type = :type_ind AND linked_id = :linked_id', {'type_ind': int(Concepts.BID), 'linked_id': bid_row[0]})
|
||||
|
||||
session.execute('DELETE FROM eventlog WHERE eventlog.linked_type = :type_ind AND eventlog.linked_id = :offer_id', {'type_ind': int(Concepts.OFFER), 'offer_id': offer_row[0]})
|
||||
session.execute('DELETE FROM automationlinks WHERE automationlinks.linked_type = :type_ind AND automationlinks.linked_id = :offer_id', {'type_ind': int(Concepts.OFFER), 'offer_id': offer_row[0]})
|
||||
|
@ -47,6 +48,7 @@ def remove_expired_data(self):
|
|||
session.execute('DELETE FROM sentoffers WHERE sentoffers.offer_id = :offer_id', {'offer_id': offer_row[0]})
|
||||
session.execute('DELETE FROM actions WHERE actions.linked_id = :offer_id', {'offer_id': offer_row[0]})
|
||||
session.execute('DELETE FROM offers WHERE offers.offer_id = :offer_id', {'offer_id': offer_row[0]})
|
||||
session.execute('DELETE FROM message_links WHERE linked_type = :type_ind AND linked_id = :linked_id', {'type_ind': int(Concepts.OFFER), 'offer_id': offer_row[0]})
|
||||
|
||||
self.log.warning(f'Removed data for {num_offers} expired offers and {num_bids} bids.')
|
||||
|
||||
|
|
|
@ -318,6 +318,27 @@ class BTCInterface(CoinInterface):
|
|||
args.append('bech32')
|
||||
return self.rpc_callback('getnewaddress', args)
|
||||
|
||||
def isValidAddress(self, address: str) -> bool:
|
||||
try:
|
||||
rv = self.rpc_callback('validateaddress', [address])
|
||||
if rv['isvalid'] is True:
|
||||
return True
|
||||
except Exception as ex:
|
||||
self._log.debug('validateaddress failed: {}'.format(address))
|
||||
return False
|
||||
|
||||
def isValidAddressHash(self, address_hash: bytes) -> bool:
|
||||
hash_len = len(address_hash)
|
||||
if hash_len == 20:
|
||||
return True
|
||||
|
||||
def isValidPubkey(self, pubkey: bytes) -> bool:
|
||||
try:
|
||||
self.verifyPubkey(pubkey)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def isAddressMine(self, address: str, or_watch_only: bool = False) -> bool:
|
||||
addr_info = self.rpc_callback('getaddressinfo', [address])
|
||||
if not or_watch_only:
|
||||
|
@ -1434,6 +1455,10 @@ class BTCInterface(CoinInterface):
|
|||
tx.rehash()
|
||||
return tx.serialize().hex()
|
||||
|
||||
def ensureFunds(self, amount):
|
||||
if self.getSpendableBalance() < amount:
|
||||
raise ValueError('Balance too low')
|
||||
|
||||
|
||||
def testBTCInterface():
|
||||
print('TODO: testBTCInterface')
|
||||
|
|
|
@ -55,7 +55,7 @@ class DASHInterface(BTCInterface):
|
|||
params = [addr_to, value, '', '', subfee, False, False, self._conf_target]
|
||||
return self.rpc_callback('sendtoaddress', params)
|
||||
|
||||
def getSpendableBalance(self):
|
||||
def getSpendableBalance(self) -> int:
|
||||
return self.make_int(self.rpc_callback('getwalletinfo')['balance'])
|
||||
|
||||
def getScriptForPubkeyHash(self, pkh: bytes) -> bytearray:
|
||||
|
|
|
@ -181,7 +181,7 @@ class FIROInterface(BTCInterface):
|
|||
def getWalletSeedID(self):
|
||||
return self.rpc_callback('getwalletinfo')['hdmasterkeyid']
|
||||
|
||||
def getSpendableBalance(self):
|
||||
def getSpendableBalance(self) -> int:
|
||||
return self.make_int(self.rpc_callback('getwalletinfo')['balance'])
|
||||
|
||||
def getBLockSpendTxFee(self, tx, fee_rate: int) -> int:
|
||||
|
|
|
@ -131,15 +131,6 @@ class PARTInterface(BTCInterface):
|
|||
block_header = self.rpc_callback('getblockheader', [block_hash])
|
||||
return block_header['height']
|
||||
|
||||
def isValidAddress(self, address: str) -> bool:
|
||||
try:
|
||||
rv = self.rpc_callback('validateaddress', [address])
|
||||
if rv['isvalid'] is True:
|
||||
return True
|
||||
except Exception as ex:
|
||||
self._log.debug('validateaddress failed: {}'.format(address))
|
||||
return False
|
||||
|
||||
|
||||
class PARTInterfaceBlind(PARTInterface):
|
||||
@staticmethod
|
||||
|
@ -648,7 +639,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
txid = self.rpc_callback('sendtypeto', params)
|
||||
return bytes.fromhex(txid)
|
||||
|
||||
def findTxB(self, kbv, Kbs, cb_swap_value, cb_block_confirmed, restore_height, bid_sender):
|
||||
def findTxB(self, kbv, Kbs, cb_swap_value, cb_block_confirmed, restore_height: int, bid_sender: bool):
|
||||
Kbv = self.getPubkey(kbv)
|
||||
sx_addr = self.formatStealthAddress(Kbv, Kbs)
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ class PIVXInterface(BTCInterface):
|
|||
params = [addr_to, value, '', '', subfee]
|
||||
return self.rpc_callback('sendtoaddress', params)
|
||||
|
||||
def getSpendableBalance(self):
|
||||
def getSpendableBalance(self) -> int:
|
||||
return self.make_int(self.rpc_callback('getwalletinfo')['balance'])
|
||||
|
||||
def loadTx(self, tx_bytes):
|
||||
|
|
|
@ -480,7 +480,7 @@ class XMRInterface(CoinInterface):
|
|||
except Exception as e:
|
||||
return {'error': str(e)}
|
||||
|
||||
def getSpendableBalance(self):
|
||||
def getSpendableBalance(self) -> int:
|
||||
with self._mx_wallet:
|
||||
self.openWallet(self._wallet_filename)
|
||||
|
||||
|
@ -514,3 +514,7 @@ class XMRInterface(CoinInterface):
|
|||
def isAddressMine(self, address):
|
||||
# TODO
|
||||
return True
|
||||
|
||||
def ensureFunds(self, amount):
|
||||
if self.getSpendableBalance() < amount:
|
||||
raise ValueError('Balance too low')
|
||||
|
|
|
@ -382,8 +382,8 @@ def js_revokeoffer(self, url_split, post_string, is_json) -> bytes:
|
|||
def js_smsgaddresses(self, url_split, post_string, is_json) -> bytes:
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
post_data = {} if post_string == '' else getFormData(post_string, is_json)
|
||||
if len(url_split) > 3:
|
||||
post_data = {} if post_string == '' else getFormData(post_string, is_json)
|
||||
if url_split[3] == 'new':
|
||||
addressnote = get_data_entry_or(post_data, 'addressnote', '')
|
||||
new_addr, pubkey = swap_client.newSMSGAddress(addressnote=addressnote)
|
||||
|
@ -400,7 +400,11 @@ def js_smsgaddresses(self, url_split, post_string, is_json) -> bytes:
|
|||
new_addr = swap_client.editSMSGAddress(address, activeind, addressnote)
|
||||
return bytes(json.dumps({'edited_address': address}), 'UTF-8')
|
||||
|
||||
return bytes(json.dumps(swap_client.listAllSMSGAddresses()), 'UTF-8')
|
||||
filters = {
|
||||
'exclude_inactive': post_data.get('exclude_inactive', True),
|
||||
}
|
||||
|
||||
return bytes(json.dumps(swap_client.listAllSMSGAddresses(filters)), 'UTF-8')
|
||||
|
||||
|
||||
def js_rates(self, url_split, post_string, is_json) -> bytes:
|
||||
|
|
|
@ -131,3 +131,23 @@ message XmrBidLockReleaseMessage {
|
|||
|
||||
bytes al_lock_spend_tx_esig = 2;
|
||||
}
|
||||
|
||||
message ADSBidIntentMessage {
|
||||
/* L -> F Sent from bidder, construct a reverse bid */
|
||||
bytes offer_msg_id = 1;
|
||||
uint64 time_valid = 2; /* seconds bid is valid for */
|
||||
uint64 amount = 3; /* amount of amount_from bid is for */
|
||||
uint64 rate = 4;
|
||||
|
||||
uint32 protocol_version = 5;
|
||||
}
|
||||
|
||||
message ADSBidIntentAcceptMessage {
|
||||
/* F -> L Sent from offerer, construct a reverse bid */
|
||||
bytes bid_msg_id = 1;
|
||||
|
||||
bytes pkaf = 2;
|
||||
bytes kbvf = 3;
|
||||
bytes kbsf_dleag = 4;
|
||||
bytes dest_af = 5;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default()
|
|||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0emessages.proto\x12\tbasicswap\"\xa6\x04\n\x0cOfferMessage\x12\x11\n\tcoin_from\x18\x01 \x01(\r\x12\x0f\n\x07\x63oin_to\x18\x02 \x01(\r\x12\x13\n\x0b\x61mount_from\x18\x03 \x01(\x04\x12\x0c\n\x04rate\x18\x04 \x01(\x04\x12\x16\n\x0emin_bid_amount\x18\x05 \x01(\x04\x12\x12\n\ntime_valid\x18\x06 \x01(\x04\x12\x33\n\tlock_type\x18\x07 \x01(\x0e\x32 .basicswap.OfferMessage.LockType\x12\x12\n\nlock_value\x18\x08 \x01(\r\x12\x11\n\tswap_type\x18\t \x01(\r\x12\x15\n\rproof_address\x18\n \x01(\t\x12\x17\n\x0fproof_signature\x18\x0b \x01(\t\x12\x15\n\rpkhash_seller\x18\x0c \x01(\x0c\x12\x13\n\x0bsecret_hash\x18\r \x01(\x0c\x12\x15\n\rfee_rate_from\x18\x0e \x01(\x04\x12\x13\n\x0b\x66\x65\x65_rate_to\x18\x0f \x01(\x04\x12\x18\n\x10protocol_version\x18\x10 \x01(\r\x12\x19\n\x11\x61mount_negotiable\x18\x11 \x01(\x08\x12\x17\n\x0frate_negotiable\x18\x12 \x01(\x08\"q\n\x08LockType\x12\x0b\n\x07NOT_SET\x10\x00\x12\x18\n\x14SEQUENCE_LOCK_BLOCKS\x10\x01\x12\x16\n\x12SEQUENCE_LOCK_TIME\x10\x02\x12\x13\n\x0f\x41\x42S_LOCK_BLOCKS\x10\x03\x12\x11\n\rABS_LOCK_TIME\x10\x04\"\xb4\x01\n\nBidMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x12\n\ntime_valid\x18\x02 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\x12\x0c\n\x04rate\x18\x04 \x01(\x04\x12\x14\n\x0cpkhash_buyer\x18\x05 \x01(\x0c\x12\x15\n\rproof_address\x18\x06 \x01(\t\x12\x17\n\x0fproof_signature\x18\x07 \x01(\t\x12\x18\n\x10protocol_version\x18\x08 \x01(\r\"V\n\x10\x42idAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x15\n\rinitiate_txid\x18\x02 \x01(\x0c\x12\x17\n\x0f\x63ontract_script\x18\x03 \x01(\x0c\"=\n\x12OfferRevokeMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x11\n\tsignature\x18\x02 \x01(\x0c\";\n\x10\x42idRejectMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x13\n\x0breject_code\x18\x02 \x01(\r\"\xb2\x01\n\rXmrBidMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x12\n\ntime_valid\x18\x02 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\x12\x0c\n\x04rate\x18\x04 \x01(\x04\x12\x0c\n\x04pkaf\x18\x05 \x01(\x0c\x12\x0c\n\x04kbvf\x18\x06 \x01(\x0c\x12\x12\n\nkbsf_dleag\x18\x07 \x01(\x0c\x12\x0f\n\x07\x64\x65st_af\x18\x08 \x01(\x0c\x12\x18\n\x10protocol_version\x18\t \x01(\r\"T\n\x0fXmrSplitMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x10\n\x08msg_type\x18\x02 \x01(\r\x12\x10\n\x08sequence\x18\x03 \x01(\r\x12\r\n\x05\x64leag\x18\x04 \x01(\x0c\"\x80\x02\n\x13XmrBidAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x0c\n\x04pkal\x18\x03 \x01(\x0c\x12\x0c\n\x04kbvl\x18\x04 \x01(\x0c\x12\x12\n\nkbsl_dleag\x18\x05 \x01(\x0c\x12\x11\n\ta_lock_tx\x18\x06 \x01(\x0c\x12\x18\n\x10\x61_lock_tx_script\x18\x07 \x01(\x0c\x12\x18\n\x10\x61_lock_refund_tx\x18\x08 \x01(\x0c\x12\x1f\n\x17\x61_lock_refund_tx_script\x18\t \x01(\x0c\x12\x1e\n\x16\x61_lock_refund_spend_tx\x18\n \x01(\x0c\x12\x1d\n\x15\x61l_lock_refund_tx_sig\x18\x0b \x01(\x0c\"r\n\x17XmrBidLockTxSigsMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12$\n\x1c\x61\x66_lock_refund_spend_tx_esig\x18\x02 \x01(\x0c\x12\x1d\n\x15\x61\x66_lock_refund_tx_sig\x18\x03 \x01(\x0c\"X\n\x18XmrBidLockSpendTxMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x17\n\x0f\x61_lock_spend_tx\x18\x02 \x01(\x0c\x12\x0f\n\x07kal_sig\x18\x03 \x01(\x0c\"M\n\x18XmrBidLockReleaseMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x1d\n\x15\x61l_lock_spend_tx_esig\x18\x02 \x01(\x0c\x62\x06proto3')
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0emessages.proto\x12\tbasicswap\"\xa6\x04\n\x0cOfferMessage\x12\x11\n\tcoin_from\x18\x01 \x01(\r\x12\x0f\n\x07\x63oin_to\x18\x02 \x01(\r\x12\x13\n\x0b\x61mount_from\x18\x03 \x01(\x04\x12\x0c\n\x04rate\x18\x04 \x01(\x04\x12\x16\n\x0emin_bid_amount\x18\x05 \x01(\x04\x12\x12\n\ntime_valid\x18\x06 \x01(\x04\x12\x33\n\tlock_type\x18\x07 \x01(\x0e\x32 .basicswap.OfferMessage.LockType\x12\x12\n\nlock_value\x18\x08 \x01(\r\x12\x11\n\tswap_type\x18\t \x01(\r\x12\x15\n\rproof_address\x18\n \x01(\t\x12\x17\n\x0fproof_signature\x18\x0b \x01(\t\x12\x15\n\rpkhash_seller\x18\x0c \x01(\x0c\x12\x13\n\x0bsecret_hash\x18\r \x01(\x0c\x12\x15\n\rfee_rate_from\x18\x0e \x01(\x04\x12\x13\n\x0b\x66\x65\x65_rate_to\x18\x0f \x01(\x04\x12\x18\n\x10protocol_version\x18\x10 \x01(\r\x12\x19\n\x11\x61mount_negotiable\x18\x11 \x01(\x08\x12\x17\n\x0frate_negotiable\x18\x12 \x01(\x08\"q\n\x08LockType\x12\x0b\n\x07NOT_SET\x10\x00\x12\x18\n\x14SEQUENCE_LOCK_BLOCKS\x10\x01\x12\x16\n\x12SEQUENCE_LOCK_TIME\x10\x02\x12\x13\n\x0f\x41\x42S_LOCK_BLOCKS\x10\x03\x12\x11\n\rABS_LOCK_TIME\x10\x04\"\xb4\x01\n\nBidMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x12\n\ntime_valid\x18\x02 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\x12\x0c\n\x04rate\x18\x04 \x01(\x04\x12\x14\n\x0cpkhash_buyer\x18\x05 \x01(\x0c\x12\x15\n\rproof_address\x18\x06 \x01(\t\x12\x17\n\x0fproof_signature\x18\x07 \x01(\t\x12\x18\n\x10protocol_version\x18\x08 \x01(\r\"V\n\x10\x42idAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x15\n\rinitiate_txid\x18\x02 \x01(\x0c\x12\x17\n\x0f\x63ontract_script\x18\x03 \x01(\x0c\"=\n\x12OfferRevokeMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x11\n\tsignature\x18\x02 \x01(\x0c\";\n\x10\x42idRejectMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x13\n\x0breject_code\x18\x02 \x01(\r\"\xb2\x01\n\rXmrBidMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x12\n\ntime_valid\x18\x02 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\x12\x0c\n\x04rate\x18\x04 \x01(\x04\x12\x0c\n\x04pkaf\x18\x05 \x01(\x0c\x12\x0c\n\x04kbvf\x18\x06 \x01(\x0c\x12\x12\n\nkbsf_dleag\x18\x07 \x01(\x0c\x12\x0f\n\x07\x64\x65st_af\x18\x08 \x01(\x0c\x12\x18\n\x10protocol_version\x18\t \x01(\r\"T\n\x0fXmrSplitMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x10\n\x08msg_type\x18\x02 \x01(\r\x12\x10\n\x08sequence\x18\x03 \x01(\r\x12\r\n\x05\x64leag\x18\x04 \x01(\x0c\"\x80\x02\n\x13XmrBidAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x0c\n\x04pkal\x18\x03 \x01(\x0c\x12\x0c\n\x04kbvl\x18\x04 \x01(\x0c\x12\x12\n\nkbsl_dleag\x18\x05 \x01(\x0c\x12\x11\n\ta_lock_tx\x18\x06 \x01(\x0c\x12\x18\n\x10\x61_lock_tx_script\x18\x07 \x01(\x0c\x12\x18\n\x10\x61_lock_refund_tx\x18\x08 \x01(\x0c\x12\x1f\n\x17\x61_lock_refund_tx_script\x18\t \x01(\x0c\x12\x1e\n\x16\x61_lock_refund_spend_tx\x18\n \x01(\x0c\x12\x1d\n\x15\x61l_lock_refund_tx_sig\x18\x0b \x01(\x0c\"r\n\x17XmrBidLockTxSigsMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12$\n\x1c\x61\x66_lock_refund_spend_tx_esig\x18\x02 \x01(\x0c\x12\x1d\n\x15\x61\x66_lock_refund_tx_sig\x18\x03 \x01(\x0c\"X\n\x18XmrBidLockSpendTxMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x17\n\x0f\x61_lock_spend_tx\x18\x02 \x01(\x0c\x12\x0f\n\x07kal_sig\x18\x03 \x01(\x0c\"M\n\x18XmrBidLockReleaseMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x1d\n\x15\x61l_lock_spend_tx_esig\x18\x02 \x01(\x0c\"w\n\x13\x41\x44SBidIntentMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x12\n\ntime_valid\x18\x02 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\x12\x0c\n\x04rate\x18\x04 \x01(\x04\x12\x18\n\x10protocol_version\x18\x05 \x01(\r\"p\n\x19\x41\x44SBidIntentAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x0c\n\x04pkaf\x18\x02 \x01(\x0c\x12\x0c\n\x04kbvf\x18\x03 \x01(\x0c\x12\x12\n\nkbsf_dleag\x18\x04 \x01(\x0c\x12\x0f\n\x07\x64\x65st_af\x18\x05 \x01(\x0c\x62\x06proto3')
|
||||
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'messages_pb2', globals())
|
||||
|
@ -44,4 +44,8 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|||
_XMRBIDLOCKSPENDTXMESSAGE._serialized_end=1707
|
||||
_XMRBIDLOCKRELEASEMESSAGE._serialized_start=1709
|
||||
_XMRBIDLOCKRELEASEMESSAGE._serialized_end=1786
|
||||
_ADSBIDINTENTMESSAGE._serialized_start=1788
|
||||
_ADSBIDINTENTMESSAGE._serialized_end=1907
|
||||
_ADSBIDINTENTACCEPTMESSAGE._serialized_start=1909
|
||||
_ADSBIDINTENTACCEPTMESSAGE._serialized_end=2021
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020-2022 tecnovert
|
||||
# Copyright (c) 2020-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
@ -23,7 +23,7 @@ INITIATE_TX_TIMEOUT = 40 * 60 # TODO: make variable per coin
|
|||
ABS_LOCK_TIME_LEEWAY = 10 * 60
|
||||
|
||||
|
||||
def buildContractScript(lock_val, secret_hash, pkh_redeem, pkh_refund, op_lock=OpCodes.OP_CHECKSEQUENCEVERIFY):
|
||||
def buildContractScript(lock_val: int, secret_hash: bytes, pkh_redeem: bytes, pkh_refund: bytes, op_lock=OpCodes.OP_CHECKSEQUENCEVERIFY) -> bytearray:
|
||||
script = bytearray([
|
||||
OpCodes.OP_IF,
|
||||
OpCodes.OP_SIZE,
|
||||
|
@ -58,7 +58,7 @@ def extractScriptSecretHash(script):
|
|||
return script[7:39]
|
||||
|
||||
|
||||
def redeemITx(self, bid_id, session):
|
||||
def redeemITx(self, bid_id: bytes, session):
|
||||
bid, offer = self.getBidAndOffer(bid_id, session)
|
||||
ci_from = self.ci(offer.coin_from)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020-2022 tecnovert
|
||||
# Copyright (c) 2020-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
@ -9,6 +9,7 @@ from sqlalchemy.orm import scoped_session
|
|||
from basicswap.util import (
|
||||
ensure,
|
||||
)
|
||||
from basicswap.interface import Curves
|
||||
from basicswap.chainparams import (
|
||||
Coins,
|
||||
)
|
||||
|
@ -37,17 +38,17 @@ def addLockRefundSigs(self, xmr_swap, ci):
|
|||
xmr_swap.a_lock_refund_tx = signed_tx
|
||||
|
||||
|
||||
def recoverNoScriptTxnWithKey(self, bid_id, encoded_key):
|
||||
def recoverNoScriptTxnWithKey(self, bid_id: bytes, encoded_key):
|
||||
self.log.info('Manually recovering %s', bid_id.hex())
|
||||
# Manually recover txn if other key is known
|
||||
session = scoped_session(self.session_factory)
|
||||
try:
|
||||
bid, xmr_swap = self.getXmrBidFromSession(session, bid_id)
|
||||
ensure(bid, 'Bid not found: {}.'.format(bid_id.hex()))
|
||||
ensure(xmr_swap, 'XMR swap not found: {}.'.format(bid_id.hex()))
|
||||
ensure(xmr_swap, 'Adaptor-sig swap not found: {}.'.format(bid_id.hex()))
|
||||
offer, xmr_offer = self.getXmrOfferFromSession(session, bid.offer_id, sent=False)
|
||||
ensure(offer, 'Offer not found: {}.'.format(bid.offer_id.hex()))
|
||||
ensure(xmr_offer, 'XMR offer not found: {}.'.format(bid.offer_id.hex()))
|
||||
ensure(xmr_offer, 'Adaptor-sig offer not found: {}.'.format(bid.offer_id.hex()))
|
||||
ci_to = self.ci(offer.coin_to)
|
||||
|
||||
for_ed25519 = True if Coins(offer.coin_to) == Coins.XMR else False
|
||||
|
@ -109,6 +110,34 @@ def getChainBRemoteSplitKey(swap_client, bid, xmr_swap, offer):
|
|||
return None
|
||||
|
||||
|
||||
def reverseBidAmountAndRate(swap_client, bid, offer) -> (int, int):
|
||||
ci_from = swap_client.ci(offer.coin_to)
|
||||
ci_to = swap_client.ci(offer.coin_from)
|
||||
bid_rate = offer.rate if bid.rate is None else bid.rate
|
||||
amount_from: int = bid.amount
|
||||
amount_to: int = int((int(amount_from) * bid_rate) // ci_from.COIN())
|
||||
reversed_rate: int = ci_to.make_int(amount_from / amount_to, r=1)
|
||||
|
||||
return amount_to, reversed_rate
|
||||
|
||||
|
||||
def setDLEAG(xmr_swap, ci_to, kbsf: bytes) -> None:
|
||||
if ci_to.curve_type() == Curves.ed25519:
|
||||
xmr_swap.kbsf_dleag = ci_to.proveDLEAG(kbsf)
|
||||
xmr_swap.pkasf = xmr_swap.kbsf_dleag[0: 33]
|
||||
elif ci_to.curve_type() == Curves.secp256k1:
|
||||
for i in range(10):
|
||||
xmr_swap.kbsf_dleag = ci_to.signRecoverable(kbsf, 'proof kbsf owned for swap')
|
||||
pk_recovered: bytes = ci_to.verifySigAndRecover(xmr_swap.kbsf_dleag, 'proof kbsf owned for swap')
|
||||
if pk_recovered == xmr_swap.pkbsf:
|
||||
break
|
||||
# self.log.debug('kbsl recovered pubkey mismatch, retrying.')
|
||||
assert (pk_recovered == xmr_swap.pkbsf)
|
||||
xmr_swap.pkasf = xmr_swap.pkbsf
|
||||
else:
|
||||
raise ValueError('Unknown curve')
|
||||
|
||||
|
||||
class XmrSwapInterface(ProtocolInterface):
|
||||
swap_type = SwapTypes.XMR_SWAP
|
||||
|
||||
|
|
|
@ -391,7 +391,7 @@
|
|||
<div class="py-3 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600">
|
||||
<span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Price in BTC (Rate)</span>
|
||||
</div>
|
||||
</th>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="priceTableBody" class="text-gray-700">
|
||||
|
@ -555,14 +555,16 @@ function lookup_rates_table() {
|
|||
|
||||
|
||||
function set_swap_type_enabled(coin_from, coin_to, swap_type) {
|
||||
const adaptor_sig_only_coins = ['6' /* XMR */, '8' /* PART_ANON */, '7' /* PART_BLIND */];
|
||||
const secret_hash_only_coins = ['11' /* PIVX */, '12' /* DASH */, '13' /* FIRO */];
|
||||
let make_hidden = false;
|
||||
if (coin_to == '6' /* XMR */ || coin_to == '8' /* PART_ANON */ || coin_to == '7' /* PART_BLIND */ || coin_from == '7' /* PART_BLIND */ ) {
|
||||
if (adaptor_sig_only_coins.includes(coin_from) || adaptor_sig_only_coins.includes(coin_to)) {
|
||||
swap_type.disabled = true;
|
||||
swap_type.value = 'xmr_swap';
|
||||
make_hidden = true;
|
||||
swap_type.classList.add('select-disabled'); // Add the class to the disabled select
|
||||
} else
|
||||
if (coin_from == '11' /* PIVX */ || coin_from == '12' /* DASH */ || coin_from == '13' /* FIRO */ ) {
|
||||
if (secret_hash_only_coins.includes(coin_from)) {
|
||||
swap_type.disabled = true;
|
||||
swap_type.value = 'seller_first';
|
||||
make_hidden = true;
|
||||
|
@ -693,4 +695,4 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
</script>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -101,6 +101,9 @@ def parseOfferFormData(swap_client, form_data, page_data, options={}):
|
|||
except Exception:
|
||||
errors.append('Unknown Coin To')
|
||||
|
||||
if coin_from == coin_to:
|
||||
errors.append('Coins from and to must be different.')
|
||||
|
||||
try:
|
||||
page_data['amt_from'] = get_data_entry(form_data, 'amt_from')
|
||||
parsed_data['amt_from'] = inputAmount(page_data['amt_from'], ci_from)
|
||||
|
@ -214,6 +217,10 @@ def parseOfferFormData(swap_client, form_data, page_data, options={}):
|
|||
|
||||
try:
|
||||
if len(errors) == 0 and page_data['swap_style'] == 'xmr':
|
||||
reverse_bid: bool = ci_from.coin_type() in swap_client.scriptless_coins
|
||||
ci_leader = ci_to if reverse_bid else ci_from
|
||||
ci_follower = ci_from if reverse_bid else ci_to
|
||||
|
||||
if have_data_entry(form_data, 'fee_rate_from'):
|
||||
page_data['from_fee_override'] = get_data_entry(form_data, 'fee_rate_from')
|
||||
parsed_data['from_fee_override'] = page_data['from_fee_override']
|
||||
|
@ -224,12 +231,12 @@ def parseOfferFormData(swap_client, form_data, page_data, options={}):
|
|||
page_data['from_fee_override'] = ci_from.format_amount(ci_from.make_int(from_fee_override, r=1))
|
||||
parsed_data['from_fee_override'] = page_data['from_fee_override']
|
||||
|
||||
lock_spend_tx_vsize = ci_from.xmr_swap_alock_spend_tx_vsize()
|
||||
lock_spend_tx_fee = ci_from.make_int(ci_from.make_int(from_fee_override, r=1) * lock_spend_tx_vsize / 1000, r=1)
|
||||
page_data['amt_from_lock_spend_tx_fee'] = ci_from.format_amount(lock_spend_tx_fee // ci_from.COIN())
|
||||
page_data['tla_from'] = ci_from.ticker()
|
||||
lock_spend_tx_vsize = ci_leader.xmr_swap_alock_spend_tx_vsize()
|
||||
lock_spend_tx_fee = ci_leader.make_int(ci_from.make_int(from_fee_override, r=1) * lock_spend_tx_vsize / 1000, r=1)
|
||||
page_data['amt_from_lock_spend_tx_fee'] = ci_from.format_amount(lock_spend_tx_fee // ci_leader.COIN())
|
||||
page_data['tla_from'] = ci_leader.ticker()
|
||||
|
||||
if coin_to == Coins.XMR:
|
||||
if ci_follower == Coins.XMR:
|
||||
if have_data_entry(form_data, 'fee_rate_to'):
|
||||
page_data['to_fee_override'] = get_data_entry(form_data, 'fee_rate_to')
|
||||
parsed_data['to_fee_override'] = page_data['to_fee_override']
|
||||
|
@ -237,7 +244,7 @@ def parseOfferFormData(swap_client, form_data, page_data, options={}):
|
|||
to_fee_override, page_data['to_fee_src'] = swap_client.getFeeRateForCoin(parsed_data['coin_to'], page_data['fee_to_conf'])
|
||||
if page_data['fee_to_extra'] > 0:
|
||||
to_fee_override += to_fee_override * (float(page_data['fee_to_extra']) / 100.0)
|
||||
page_data['to_fee_override'] = ci_to.format_amount(ci_to.make_int(to_fee_override, r=1))
|
||||
page_data['to_fee_override'] = ci_follower.format_amount(ci_follower.make_int(to_fee_override, r=1))
|
||||
parsed_data['to_fee_override'] = page_data['to_fee_override']
|
||||
except Exception as e:
|
||||
print('Error setting fee', str(e)) # Expected if missing fields
|
||||
|
@ -596,17 +603,22 @@ def page_offer(self, url_split, post_string):
|
|||
data['debug_ind'] = debugind
|
||||
data['debug_options'] = [(int(t), t.name) for t in DebugTypes]
|
||||
|
||||
reverse_bid: bool = ci_from.coin_type() in swap_client.scriptless_coins
|
||||
ci_leader = ci_to if reverse_bid else ci_from
|
||||
ci_follower = ci_from if reverse_bid else ci_to
|
||||
|
||||
if xmr_offer:
|
||||
int_fee_rate_now, fee_source = ci_from.get_fee_rate()
|
||||
int_fee_rate_now, fee_source = ci_leader.get_fee_rate()
|
||||
|
||||
data['xmr_type'] = True
|
||||
data['a_fee_rate'] = ci_from.format_amount(xmr_offer.a_fee_rate)
|
||||
data['a_fee_rate_verify'] = ci_from.format_amount(int_fee_rate_now, conv_int=True)
|
||||
data['a_fee_rate'] = ci_leader.format_amount(xmr_offer.a_fee_rate)
|
||||
data['a_fee_rate_verify'] = ci_leader.format_amount(int_fee_rate_now, conv_int=True)
|
||||
data['a_fee_rate_verify_src'] = fee_source
|
||||
data['a_fee_warn'] = xmr_offer.a_fee_rate < int_fee_rate_now
|
||||
|
||||
lock_spend_tx_vsize = ci_from.xmr_swap_alock_spend_tx_vsize()
|
||||
lock_spend_tx_fee = ci_from.make_int(xmr_offer.a_fee_rate * lock_spend_tx_vsize / 1000, r=1)
|
||||
data['amt_from_lock_spend_tx_fee'] = ci_from.format_amount(lock_spend_tx_fee // ci_from.COIN())
|
||||
lock_spend_tx_vsize = ci_leader.xmr_swap_alock_spend_tx_vsize()
|
||||
lock_spend_tx_fee = ci_leader.make_int(xmr_offer.a_fee_rate * lock_spend_tx_vsize / 1000, r=1)
|
||||
data['amt_from_lock_spend_tx_fee'] = ci_leader.format_amount(lock_spend_tx_fee // ci_leader.COIN())
|
||||
|
||||
if offer.was_sent:
|
||||
try:
|
||||
|
@ -621,7 +633,7 @@ def page_offer(self, url_split, post_string):
|
|||
amt_swapped = 0
|
||||
for b in bids:
|
||||
amt_swapped += b[4]
|
||||
formatted_bids.append((b[2].hex(), ci_from.format_amount(b[4]), strBidState(b[5]), ci_to.format_amount(b[10]), b[11]))
|
||||
formatted_bids.append((b[2].hex(), ci_leader.format_amount(b[4]), strBidState(b[5]), ci_follower.format_amount(b[10]), b[11]))
|
||||
data['amt_swapped'] = ci_from.format_amount(amt_swapped)
|
||||
|
||||
template = server.env.get_template('offer.html')
|
||||
|
|
|
@ -28,10 +28,10 @@ from basicswap.basicswap_util import (
|
|||
getLastBidState,
|
||||
)
|
||||
|
||||
from basicswap.protocols.xmr_swap_1 import getChainBSplitKey, getChainBRemoteSplitKey
|
||||
from basicswap.protocols.xmr_swap_1 import getChainBSplitKey, getChainBRemoteSplitKey, reverseBidAmountAndRate
|
||||
|
||||
PAGE_LIMIT = 50
|
||||
invalid_coins_from = (Coins.XMR, Coins.PART_ANON)
|
||||
invalid_coins_from = []
|
||||
|
||||
|
||||
def tickerToCoinId(ticker):
|
||||
|
@ -151,6 +151,15 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
|
|||
ticker_from = ci_from.ticker()
|
||||
ticker_to = ci_to.ticker()
|
||||
|
||||
reverse_bid: bool = ci_from.coin_type() in swap_client.scriptless_coins
|
||||
ci_leader = ci_to if reverse_bid else ci_from
|
||||
ci_follower = ci_from if reverse_bid else ci_to
|
||||
|
||||
bid_amount = bid.amount
|
||||
bid_rate = offer.rate if bid.rate is None else bid.rate
|
||||
if reverse_bid:
|
||||
bid_amount, bid_rate = reverseBidAmountAndRate(swap_client, bid, offer)
|
||||
|
||||
state_description = ''
|
||||
if offer.swap_type == SwapTypes.SELLER_FIRST:
|
||||
if bid.state == BidStates.BID_SENT:
|
||||
|
@ -229,7 +238,6 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
|
|||
state_description = 'Redeeming output'
|
||||
|
||||
addr_label = swap_client.getAddressLabel([bid.bid_addr, ])[0]
|
||||
bid_rate = offer.rate if bid.rate is None else bid.rate
|
||||
|
||||
can_abandon: bool = False
|
||||
if swap_client.debug and bid.state not in (BidStates.BID_ABANDONED, BidStates.SWAP_COMPLETED):
|
||||
|
@ -238,8 +246,8 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
|
|||
data = {
|
||||
'coin_from': ci_from.coin_name(),
|
||||
'coin_to': ci_to.coin_name(),
|
||||
'amt_from': ci_from.format_amount(bid.amount),
|
||||
'amt_to': ci_to.format_amount((bid.amount * bid_rate) // ci_from.COIN()),
|
||||
'amt_from': ci_from.format_amount(bid_amount),
|
||||
'amt_to': ci_to.format_amount((bid_amount * bid_rate) // ci_from.COIN()),
|
||||
'bid_rate': ci_to.format_amount(bid_rate),
|
||||
'ticker_from': ticker_from,
|
||||
'ticker_to': ticker_to,
|
||||
|
@ -335,16 +343,16 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
|
|||
|
||||
if offer.lock_type == TxLockTypes.SEQUENCE_LOCK_TIME:
|
||||
if bid.xmr_a_lock_tx and bid.xmr_a_lock_tx.block_time:
|
||||
raw_sequence = ci_from.getExpectedSequence(offer.lock_type, offer.lock_value)
|
||||
seconds_locked = ci_from.decodeSequence(raw_sequence)
|
||||
raw_sequence = ci_leader.getExpectedSequence(offer.lock_type, offer.lock_value)
|
||||
seconds_locked = ci_leader.decodeSequence(raw_sequence)
|
||||
data['coin_a_lock_refund_tx_est_final'] = bid.xmr_a_lock_tx.block_time + seconds_locked
|
||||
data['coin_a_last_median_time'] = swap_client.coin_clients[offer.coin_from]['chain_median_time']
|
||||
|
||||
if TxTypes.XMR_SWAP_A_LOCK_REFUND in bid.txns:
|
||||
refund_tx = bid.txns[TxTypes.XMR_SWAP_A_LOCK_REFUND]
|
||||
if refund_tx.block_time is not None:
|
||||
raw_sequence = ci_from.getExpectedSequence(offer.lock_type, offer.lock_value)
|
||||
seconds_locked = ci_from.decodeSequence(raw_sequence)
|
||||
raw_sequence = ci_leader.getExpectedSequence(offer.lock_type, offer.lock_value)
|
||||
seconds_locked = ci_leader.decodeSequence(raw_sequence)
|
||||
data['coin_a_lock_refund_swipe_tx_est_final'] = refund_tx.block_time + seconds_locked
|
||||
|
||||
if view_tx_ind:
|
||||
|
@ -367,12 +375,12 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
|
|||
else:
|
||||
if offer.lock_type == TxLockTypes.SEQUENCE_LOCK_TIME:
|
||||
if bid.initiate_tx and bid.initiate_tx.block_time is not None:
|
||||
raw_sequence = ci_from.getExpectedSequence(offer.lock_type, offer.lock_value)
|
||||
seconds_locked = ci_from.decodeSequence(raw_sequence)
|
||||
raw_sequence = ci_leader.getExpectedSequence(offer.lock_type, offer.lock_value)
|
||||
seconds_locked = ci_leader.decodeSequence(raw_sequence)
|
||||
data['itx_refund_tx_est_final'] = bid.initiate_tx.block_time + seconds_locked
|
||||
if bid.participate_tx and bid.participate_tx.block_time is not None:
|
||||
raw_sequence = ci_to.getExpectedSequence(offer.lock_type, offer.lock_value // 2)
|
||||
seconds_locked = ci_to.decodeSequence(raw_sequence)
|
||||
raw_sequence = ci_follower.getExpectedSequence(offer.lock_type, offer.lock_value // 2)
|
||||
seconds_locked = ci_follower.decodeSequence(raw_sequence)
|
||||
data['ptx_refund_tx_est_final'] = bid.participate_tx.block_time + seconds_locked
|
||||
|
||||
return data
|
||||
|
|
|
@ -121,7 +121,7 @@ def stopDaemons(daemons):
|
|||
logging.info('Closing %d, error %s', d.pid, str(e))
|
||||
|
||||
|
||||
def wait_for_bid(delay_event, swap_client, bid_id, state=None, sent=False, wait_for=20):
|
||||
def wait_for_bid(delay_event, swap_client, bid_id, state=None, sent: bool = False, wait_for: int = 20) -> None:
|
||||
logging.info('wait_for_bid %s', bid_id.hex())
|
||||
for i in range(wait_for):
|
||||
if delay_event.is_set():
|
||||
|
|
|
@ -63,6 +63,18 @@ class BasicSwapTest(BaseTest):
|
|||
def mineBlock(self, num_blocks=1):
|
||||
self.callnoderpc('generatetoaddress', [num_blocks, self.btc_addr])
|
||||
|
||||
def prepare_balance(self, coin_ticker: str, amount: float, port_target_node: int, port_take_from_node: int) -> None:
|
||||
js_w = read_json_api(port_target_node, 'wallets')
|
||||
if float(js_w[coin_ticker]['balance']) < amount:
|
||||
post_json = {
|
||||
'value': amount,
|
||||
'address': js_w[coin_ticker]['deposit_address'],
|
||||
'subfee': False,
|
||||
}
|
||||
json_rv = read_json_api(port_take_from_node, 'wallets/{}/withdraw'.format(coin_ticker.lower()), post_json)
|
||||
assert (len(json_rv['txid']) == 64)
|
||||
wait_for_balance(test_delay_event, 'http://127.0.0.1:{}/json/wallets/{}'.format(port_target_node, coin_ticker.lower()), 'balance', amount)
|
||||
|
||||
def test_001_nested_segwit(self):
|
||||
logging.info('---------- Test {} p2sh nested segwit'.format(self.test_coin_from.name))
|
||||
|
||||
|
@ -263,7 +275,7 @@ class BasicSwapTest(BaseTest):
|
|||
rv = read_json_api(1800, 'getcoinseed', {'coin': 'XMR'})
|
||||
assert (rv['address'] == '47H7UDLzYEsR28BWttxp59SP1UVSxs4VKDJYSfmz7Wd4Fue5VWuoV9x9eejunwzVSmHWN37gBkaAPNf9VD4bTvwQKsBVWyK')
|
||||
|
||||
def do_test_01_full_swap(self, coin_from, coin_to):
|
||||
def do_test_01_full_swap(self, coin_from: Coins, coin_to: Coins) -> None:
|
||||
logging.info('---------- Test {} to {}'.format(coin_from.name, coin_to.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
|
@ -289,8 +301,7 @@ class BasicSwapTest(BaseTest):
|
|||
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)
|
||||
|
||||
swap_clients[0].acceptXmrBid(bid_id)
|
||||
swap_clients[0].acceptBid(bid_id)
|
||||
|
||||
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)
|
||||
|
@ -317,63 +328,83 @@ class BasicSwapTest(BaseTest):
|
|||
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):
|
||||
def test_01_a_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):
|
||||
def test_01_b_full_swap_reverse(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.prepare_balance(Coins.XMR.name, 100.0, 1800, 1801)
|
||||
self.do_test_01_full_swap(Coins.XMR, self.test_coin_from)
|
||||
|
||||
def test_01_c_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):
|
||||
def test_01_d_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):
|
||||
def do_test_02_leader_recover_a_lock_tx(self, coin_from: Coins, coin_to: Coins) -> None:
|
||||
logging.info('---------- Test {} to {} leader recovers coin a lock tx'.format(coin_from.name, coin_to.name))
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
reverse_bid: bool = coin_from in swap_clients[0].scriptless_coins
|
||||
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, coin_from)
|
||||
# Offerer sends the offer
|
||||
# Bidder sends the bid
|
||||
id_offerer: int = 0
|
||||
id_bidder: int = 1
|
||||
|
||||
# Leader sends the initial (chain a) lock tx.
|
||||
# Follower sends the participate (chain b) lock tx.
|
||||
id_leader: int = 1 if reverse_bid else 0
|
||||
id_follower: int = 0 if reverse_bid else 1
|
||||
logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}')
|
||||
|
||||
js_wl_before = read_json_api(1800 + id_leader, 'wallets')
|
||||
wl_from_before = self.getBalance(js_wl_before, coin_from)
|
||||
|
||||
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(
|
||||
offer_id = swap_clients[id_offerer].postOffer(
|
||||
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)
|
||||
wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id)
|
||||
offer = swap_clients[id_bidder].getOffer(offer_id)
|
||||
|
||||
bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from)
|
||||
bid_id = swap_clients[id_bidder].postXmrBid(offer_id, offer.amount_from)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED)
|
||||
swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK)
|
||||
swap_clients[id_offerer].acceptBid(bid_id)
|
||||
|
||||
bid, xmr_swap = swap_clients[0].getXmrBid(bid_id)
|
||||
assert (xmr_swap)
|
||||
leader_sent_bid: bool = True if reverse_bid else False
|
||||
wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=leader_sent_bid, wait_for=180)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, [BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED], sent=(not leader_sent_bid))
|
||||
|
||||
swap_clients[1].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK)
|
||||
|
||||
swap_clients[0].acceptXmrBid(bid_id)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180)
|
||||
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, coin_from)
|
||||
js_wl_after = read_json_api(1800 + id_leader, 'wallets')
|
||||
wl_from_after = self.getBalance(js_wl_after, coin_from)
|
||||
|
||||
# TODO: Discard block rewards
|
||||
# assert (node0_from_before - node0_from_after < 0.02)
|
||||
|
||||
def test_02_leader_recover_a_lock_tx(self):
|
||||
def test_02_a_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):
|
||||
def test_02_b_leader_recover_a_lock_tx_reverse(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.prepare_balance(Coins.XMR.name, 100.0, 1800, 1801)
|
||||
self.do_test_02_leader_recover_a_lock_tx(Coins.XMR, self.test_coin_from)
|
||||
|
||||
def test_02_c_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)
|
||||
|
@ -384,34 +415,42 @@ class BasicSwapTest(BaseTest):
|
|||
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))
|
||||
|
||||
# Leader is too slow to recover the coin a lock tx and follower swipes it
|
||||
# coin b lock tx remains unspent
|
||||
|
||||
swap_clients = self.swap_clients
|
||||
reverse_bid: bool = coin_from in swap_clients[0].scriptless_coins
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
id_offerer: int = 0
|
||||
id_bidder: int = 1
|
||||
id_leader: int = 1 if reverse_bid else 0
|
||||
id_follower: int = 0 if reverse_bid else 1
|
||||
logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}')
|
||||
|
||||
js_w0_before = read_json_api(1800, 'wallets')
|
||||
js_w1_before = read_json_api(1801, 'wallets')
|
||||
|
||||
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(
|
||||
offer_id = swap_clients[id_offerer].postOffer(
|
||||
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)
|
||||
offer = swap_clients[id_bidder].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_id = swap_clients[id_bidder].postXmrBid(offer_id, offer.amount_from)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED)
|
||||
|
||||
bid, xmr_swap = swap_clients[0].getXmrBid(bid_id)
|
||||
assert (xmr_swap)
|
||||
swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK)
|
||||
swap_clients[id_leader].setBidDebugInd(bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND)
|
||||
|
||||
swap_clients[1].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK)
|
||||
swap_clients[0].setBidDebugInd(bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND)
|
||||
swap_clients[id_offerer].acceptBid(bid_id)
|
||||
|
||||
swap_clients[0].acceptXmrBid(bid_id)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_STALLED_FOR_TEST, wait_for=180)
|
||||
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_SWIPED, wait_for=80, sent=True)
|
||||
leader_sent_bid: bool = True if reverse_bid else False
|
||||
wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, BidStates.BID_STALLED_FOR_TEST, wait_for=180, sent=leader_sent_bid)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, BidStates.XMR_SWAP_FAILED_SWIPED, wait_for=80, sent=(not leader_sent_bid))
|
||||
|
||||
js_w1_after = read_json_api(1801, 'wallets')
|
||||
|
||||
|
@ -426,74 +465,97 @@ class BasicSwapTest(BaseTest):
|
|||
wait_for_none_active(test_delay_event, 1800)
|
||||
wait_for_none_active(test_delay_event, 1801)
|
||||
|
||||
def test_03_follower_recover_a_lock_tx(self):
|
||||
def test_03_a_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):
|
||||
def test_03_b_follower_recover_a_lock_tx_reverse(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.prepare_balance(Coins.XMR.name, 100.0, 1800, 1801)
|
||||
self.do_test_03_follower_recover_a_lock_tx(Coins.XMR, self.test_coin_from)
|
||||
|
||||
def test_03_c_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):
|
||||
def test_03_d_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
|
||||
reverse_bid: bool = coin_from in swap_clients[0].scriptless_coins
|
||||
ci_from = swap_clients[0].ci(coin_from)
|
||||
ci_to = swap_clients[0].ci(coin_to)
|
||||
|
||||
id_offerer: int = 0
|
||||
id_bidder: int = 1
|
||||
id_leader: int = 1 if reverse_bid else 0
|
||||
id_follower: int = 0 if reverse_bid else 1
|
||||
logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}')
|
||||
|
||||
js_w0_before = read_json_api(1800, 'wallets')
|
||||
js_w1_before = read_json_api(1801, 'wallets')
|
||||
|
||||
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(
|
||||
offer_id = swap_clients[id_offerer].postOffer(
|
||||
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)
|
||||
wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id)
|
||||
offer = swap_clients[id_bidder].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_id = swap_clients[id_bidder].postXmrBid(offer_id, offer.amount_from)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED)
|
||||
|
||||
bid, xmr_swap = swap_clients[0].getXmrBid(bid_id)
|
||||
assert (xmr_swap)
|
||||
swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK)
|
||||
swap_clients[id_offerer].acceptBid(bid_id)
|
||||
|
||||
swap_clients[1].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK)
|
||||
swap_clients[0].acceptXmrBid(bid_id)
|
||||
|
||||
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180)
|
||||
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=True)
|
||||
leader_sent_bid: bool = True if reverse_bid else False
|
||||
wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=200, sent=leader_sent_bid)
|
||||
wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=(not leader_sent_bid))
|
||||
|
||||
js_w0_after = read_json_api(1800, 'wallets')
|
||||
js_w1_after = read_json_api(1801, 'wallets')
|
||||
|
||||
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)
|
||||
logging.info('node0 end coin_from balance {}, diff {}'.format(node0_from_after, node0_from_after - node0_from_before))
|
||||
node0_to_before = self.getBalance(js_w0_before, coin_to)
|
||||
node0_to_after = self.getBalance(js_w0_after, coin_to)
|
||||
logging.info('node0 end coin_to balance {}, diff {}'.format(node0_to_after, node0_to_after - node0_to_before))
|
||||
if coin_from != Coins.PART: # TODO: Discard block rewards
|
||||
assert (node0_from_before - node0_from_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)
|
||||
node1_from_before = self.getBalance(js_w1_before, coin_from)
|
||||
node1_from_after = self.getBalance(js_w1_after, coin_from)
|
||||
logging.info('node1 end coin_from balance {}, diff {}'.format(node1_from_after, node1_from_after - node1_from_before))
|
||||
node1_to_before = self.getBalance(js_w1_before, coin_to)
|
||||
node1_to_after = self.getBalance(js_w1_after, coin_to)
|
||||
logging.info('node1 end coin_to balance {}, diff {}'.format(node1_to_after, node1_to_after - node1_to_before))
|
||||
assert (node1_to_before - node1_to_after < 0.02)
|
||||
|
||||
def test_04_follower_recover_b_lock_tx(self):
|
||||
def test_04_a_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):
|
||||
def test_04_b_follower_recover_b_lock_tx_reverse(self):
|
||||
if not self.has_segwit:
|
||||
return
|
||||
self.prepare_balance(Coins.XMR.name, 100.0, 1800, 1801)
|
||||
self.do_test_04_follower_recover_b_lock_tx(Coins.XMR, self.test_coin_from)
|
||||
|
||||
def test_04_c_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):
|
||||
def test_04_d_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):
|
||||
|
@ -528,17 +590,7 @@ class BasicSwapTest(BaseTest):
|
|||
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)
|
||||
self.prepare_balance(tla_from, 100.0, 1802, 1800)
|
||||
|
||||
js_w2 = read_json_api(1802, 'wallets')
|
||||
assert (float(js_w2[tla_from]['balance']) >= 100.0)
|
||||
|
|
|
@ -88,6 +88,9 @@ from tests.basicswap.common import (
|
|||
LTC_BASE_RPC_PORT,
|
||||
PREFIX_SECRET_KEY_REGTEST,
|
||||
)
|
||||
from basicswap.db_util import (
|
||||
remove_expired_data,
|
||||
)
|
||||
from bin.basicswap_run import startDaemon, startXmrDaemon
|
||||
|
||||
|
||||
|
@ -744,6 +747,12 @@ class Test(BaseTest):
|
|||
assert (json_rv['edited_address'] == new_address)
|
||||
|
||||
js_3 = read_json_api(1801, 'smsgaddresses')
|
||||
assert (len(js_3) == 0)
|
||||
|
||||
post_json = {
|
||||
'exclude_inactive': False,
|
||||
}
|
||||
js_3 = json.loads(post_json_req('http://127.0.0.1:1801/json/smsgaddresses', post_json))
|
||||
found = False
|
||||
for addr in js_3:
|
||||
if addr['addr'] == new_address:
|
||||
|
@ -1356,7 +1365,7 @@ class Test(BaseTest):
|
|||
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=1800)
|
||||
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=1800, sent=True)
|
||||
|
||||
def test_98_withdraw_all(self):
|
||||
def test_97_withdraw_all(self):
|
||||
logging.info('---------- Test XMR withdrawal all')
|
||||
try:
|
||||
logging.info('Disabling XMR mining')
|
||||
|
@ -1384,6 +1393,9 @@ class Test(BaseTest):
|
|||
logging.info('Restoring XMR mining')
|
||||
pause_event.set()
|
||||
|
||||
def test_98_remove_expired_data(self):
|
||||
remove_expired_data(self.swap_clients[0])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
Loading…
Reference in a new issue