diff --git a/basicswap/__init__.py b/basicswap/__init__.py index a9e322c..08e5b09 100644 --- a/basicswap/__init__.py +++ b/basicswap/__init__.py @@ -1,3 +1,3 @@ name = "basicswap" -__version__ = "0.0.22" +__version__ = "0.0.23" diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py index 98e5d94..4039bc0 100644 --- a/basicswap/basicswap.py +++ b/basicswap/basicswap.py @@ -99,6 +99,7 @@ from .basicswap_util import ( SEQUENCE_LOCK_TIME, ABS_LOCK_BLOCKS, ABS_LOCK_TIME, + AddressTypes, MessageTypes, SwapTypes, OfferStates, @@ -119,6 +120,14 @@ from .basicswap_util import ( isActiveBidState) +def validOfferStateToReceiveBid(offer_state): + if offer_state == OfferStates.OFFER_RECEIVED: + return True + if offer_state == OfferStates.OFFER_SENT: + return True + return False + + def threadPollChainState(swap_client, coin_type): while not swap_client.delay_event.is_set(): try: @@ -562,7 +571,11 @@ class BasicSwap(BaseApp): session.execute('ALTER TABLE smsgaddresses ADD COLUMN active_ind INTEGER') session.execute('ALTER TABLE smsgaddresses ADD COLUMN created_at INTEGER') session.execute('ALTER TABLE smsgaddresses ADD COLUMN note VARCHAR') + session.execute('ALTER TABLE smsgaddresses ADD COLUMN pubkey VARCHAR') session.execute('UPDATE smsgaddresses SET active_ind = 1, created_at = 1') + + session.execute('ALTER TABLE offers ADD COLUMN addr_to VARCHAR') + session.execute(f'UPDATE offers SET addr_to = "{self.network_addr}"') db_version += 1 if current_version != db_version: @@ -859,6 +872,11 @@ class BasicSwap(BaseApp): if valid_for_seconds > 24 * 60 * 60: raise ValueError('Bid TTL too high') + def getOfferAddressTo(self, extra_options): + if 'addr_send_to' in extra_options: + return extra_options['addr_send_to'] + return self.network_addr + def postOffer(self, coin_from, coin_to, amount, rate, min_bid_amount, swap_type, lock_type=SEQUENCE_LOCK_TIME, lock_value=48 * 60 * 60, auto_accept_bids=False, addr_send_from=None, extra_options={}): # Offer to send offer.amount_from of coin_from in exchange for offer.amount_from * offer.rate of coin_to @@ -882,6 +900,8 @@ class BasicSwap(BaseApp): self.validateOfferLockValue(coin_from_t, coin_to_t, lock_type, lock_value) self.validateOfferValidTime(swap_type, coin_from_t, coin_to_t, valid_for_seconds) + offer_addr_to = self.getOfferAddressTo(extra_options) + self.mxDB.acquire() session = None try: @@ -948,7 +968,7 @@ class BasicSwap(BaseApp): self.callrpc('smsgaddlocaladdress', [offer_addr]) # Enable receiving smsg options = {'decodehex': True, 'ttl_is_seconds': True} msg_valid = max(self.SMSG_SECONDS_IN_HOUR * 1, valid_for_seconds) - ro = self.callrpc('smsgsend', [offer_addr, self.network_addr, payload_hex, False, msg_valid, False, options]) + ro = self.callrpc('smsgsend', [offer_addr, offer_addr_to, payload_hex, False, msg_valid, False, options]) msg_id = ro['msgid'] offer_id = bytes.fromhex(msg_id) @@ -972,6 +992,7 @@ class BasicSwap(BaseApp): lock_value=msg_buf.lock_value, swap_type=msg_buf.swap_type, + addr_to=offer_addr_to, addr_from=offer_addr, created_at=offer_created_at, expire_at=offer_created_at + msg_buf.time_valid, @@ -987,7 +1008,7 @@ class BasicSwap(BaseApp): session.add(offer) session.add(SentOffer(offer_id=offer_id)) if addr_send_from is None: - session.add(SmsgAddress(addr=offer_addr, use_type=MessageTypes.OFFER, active_ind=1, created_at=offer_created_at)) + session.add(SmsgAddress(addr=offer_addr, use_type=AddressTypes.OFFER, active_ind=1, created_at=offer_created_at)) session.commit() finally: @@ -1542,7 +1563,7 @@ class BasicSwap(BaseApp): session = scoped_session(self.session_factory) self.saveBidInSession(bid_id, bid, session) if addr_send_from is None: - session.add(SmsgAddress(addr=bid_addr, use_type=MessageTypes.BID, active_ind=1, created_at=now)) + session.add(SmsgAddress(addr=bid_addr, use_type=AddressTypes.BID, active_ind=1, created_at=now)) session.commit() finally: session.close() @@ -1913,7 +1934,7 @@ class BasicSwap(BaseApp): session = scoped_session(self.session_factory) self.saveBidInSession(xmr_swap.bid_id, bid, session, xmr_swap) if addr_send_from is None: - session.add(SmsgAddress(addr=bid_addr, use_type=MessageTypes.BID, active_ind=1, created_at=bid_created_at)) + session.add(SmsgAddress(addr=bid_addr, use_type=AddressTypes.BID, active_ind=1, created_at=bid_created_at)) session.commit() finally: session.close() @@ -3376,8 +3397,6 @@ class BasicSwap(BaseApp): self.mxDB.release() def processOffer(self, msg): - assert(msg['to'] == self.network_addr), 'Offer received on wrong address' - offer_bytes = bytes.fromhex(msg['hex'][2:-2]) offer_data = OfferMessage() offer_data.ParseFromString(offer_bytes) @@ -3419,6 +3438,14 @@ class BasicSwap(BaseApp): session = scoped_session(self.session_factory) try: + # Offers must be received on the public network_addr or manually created addresses + if msg['to'] != self.network_addr: + # Double check active_ind, shouldn't be possible to receive message if not active + query_str = 'SELECT COUNT(addr_id) FROM smsgaddresses WHERE addr = "{}" AND use_type = {} AND active_ind = 1'.format(msg['to'], AddressTypes.RECV_OFFER) + rv = session.execute(query_str).first() + if rv[0] < 1: + raise ValueError('Offer received on incorrect address') + # Check for sent existing_offer = self.getOffer(offer_id) if existing_offer is None: @@ -3436,6 +3463,7 @@ class BasicSwap(BaseApp): lock_value=offer_data.lock_value, swap_type=offer_data.swap_type, + addr_to=msg['to'], addr_from=msg['from'], created_at=msg['sent'], expire_at=msg['sent'] + offer_data.time_valid, @@ -3808,7 +3836,8 @@ class BasicSwap(BaseApp): ci_from = self.ci(offer.coin_from) ci_to = self.ci(offer.coin_to) - assert(offer.state == OfferStates.OFFER_RECEIVED), 'Bad offer state' + if not validOfferStateToReceiveBid(offer.state): + raise ValueError('Bad offer state') assert(msg['to'] == offer.addr_from), 'Received on incorrect address' assert(now <= offer.expire_at), 'Offer expired' assert(bid_data.amount >= offer.min_bid_amount), 'Bid amount below minimum' @@ -4307,9 +4336,8 @@ class BasicSwap(BaseApp): kbsf = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 2, for_ed25519) vkbs = ci_to.sumKeys(kbsl, kbsf) - address_to = ci_to.getMainWalletAddress() - try: + address_to = ci_to.getMainWalletAddress() txid = ci_to.spendBLockTx(address_to, xmr_swap.vkbv, vkbs, bid.amount_to, xmr_offer.b_fee_rate, xmr_swap.b_restore_height) self.log.debug('Submitted lock B refund txn %s to %s chain for bid %s', txid.hex(), ci_to.coin_name(), bid_id.hex()) self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_B_REFUND_TX_PUBLISHED, '', session) @@ -5054,7 +5082,7 @@ class BasicSwap(BaseApp): try: session = scoped_session(self.session_factory) rv = [] - query_str = f'SELECT addr_id, addr, use_type, active_ind, created_at, note FROM smsgaddresses {filters} ORDER BY created_at' + query_str = f'SELECT addr_id, addr, use_type, active_ind, created_at, note, pubkey FROM smsgaddresses {filters} ORDER BY created_at' q = session.execute(query_str) for row in q: @@ -5065,6 +5093,7 @@ class BasicSwap(BaseApp): 'active_ind': row[3], 'created_at': row[4], 'note': row[5], + 'pubkey': row[6], }) return rv finally: @@ -5072,21 +5101,36 @@ class BasicSwap(BaseApp): session.remove() self.mxDB.release() - #listening_keys = self.callcoinrpc(Coins.PART, 'smsglocalkeys', []) - return [] - - def addSMSGAddress(self, addressnote=None): + def newSMSGAddress(self, addressnote=None): # TODO: smsg addresses should be generated from a unique chain self.mxDB.acquire() try: session = scoped_session(self.session_factory) now = int(time.time()) new_addr = self.callrpc('getnewaddress') + addr_info = self.callrpc('getaddressinfo', [new_addr]) self.callrpc('smsgaddlocaladdress', [new_addr]) # Enable receiving smsgs - session.add(SmsgAddress(addr=new_addr, use_type=MessageTypes.OFFER, active_ind=1, created_at=now, note=addressnote)) + session.add(SmsgAddress(addr=new_addr, use_type=AddressTypes.RECV_OFFER, active_ind=1, created_at=now, note=addressnote, pubkey=addr_info['pubkey'])) session.commit() - return new_addr + return new_addr, addr_info['pubkey'] + finally: + session.close() + session.remove() + self.mxDB.release() + + def addSMSGAddress(self, pubkey_hex, addressnote=None): + self.mxDB.acquire() + try: + session = scoped_session(self.session_factory) + now = int(time.time()) + ci = self.ci(Coins.PART) + add_addr = ci.pubkey_to_address(bytes.fromhex(pubkey_hex)) + self.callrpc('smsgaddaddress', [add_addr, pubkey_hex]) + + session.add(SmsgAddress(addr=add_addr, use_type=AddressTypes.SEND_OFFER, active_ind=1, created_at=now, note=addressnote, pubkey=pubkey_hex)) + session.commit() + return add_addr finally: session.close() session.remove() @@ -5107,7 +5151,15 @@ class BasicSwap(BaseApp): self.mxDB.release() def listSmsgAddresses(self, use_type_str): - use_type = MessageTypes.OFFER if use_type_str == 'offer' else MessageTypes.BID + if use_type_str == 'offer_send_from': + use_type = AddressTypes.OFFER + elif use_type_str == 'offer_send_to': + use_type = AddressTypes.SEND_OFFER + elif use_type_str == 'bid': + use_type = AddressTypes.BID + else: + raise ValueError('Unknown address type') + self.mxDB.acquire() try: session = scoped_session(self.session_factory) diff --git a/basicswap/basicswap_util.py b/basicswap/basicswap_util.py index f366329..e3aa942 100644 --- a/basicswap/basicswap_util.py +++ b/basicswap/basicswap_util.py @@ -38,6 +38,13 @@ class MessageTypes(IntEnum): OFFER_REVOKE = auto() +class AddressTypes(IntEnum): + OFFER = auto() + BID = auto() + RECV_OFFER = auto() + SEND_OFFER = auto() + + class SwapTypes(IntEnum): SELLER_FIRST = auto() BUYER_FIRST = auto() @@ -239,11 +246,15 @@ def strTxType(tx_type): return 'Unknown' -def strMessageType(msg_type): - if msg_type == MessageTypes.OFFER: - return 'Offers' - if msg_type == MessageTypes.BID: - return 'Bids' +def strAddressType(addr_type): + if addr_type == AddressTypes.OFFER: + return 'Offer' + if addr_type == AddressTypes.BID: + return 'Bid' + if addr_type == AddressTypes.RECV_OFFER: + return 'Offer recv' + if addr_type == AddressTypes.SEND_OFFER: + return 'Offer send' return 'Unknown' diff --git a/basicswap/db.py b/basicswap/db.py index d7d7909..328296d 100644 --- a/basicswap/db.py +++ b/basicswap/db.py @@ -57,6 +57,7 @@ class Offer(Base): secret_hash = sa.Column(sa.LargeBinary) addr_from = sa.Column(sa.String) + addr_to = sa.Column(sa.String) created_at = sa.Column(sa.BigInteger) expire_at = sa.Column(sa.BigInteger) was_sent = sa.Column(sa.Boolean) @@ -218,6 +219,7 @@ class SmsgAddress(Base): active_ind = sa.Column(sa.Integer) created_at = sa.Column(sa.BigInteger) addr = sa.Column(sa.String, unique=True) + pubkey = sa.Column(sa.String) use_type = sa.Column(sa.Integer) note = sa.Column(sa.String) diff --git a/basicswap/http_server.py b/basicswap/http_server.py index dbac543..c45c8d2 100644 --- a/basicswap/http_server.py +++ b/basicswap/http_server.py @@ -27,7 +27,7 @@ from .basicswap_util import ( strOfferState, strBidState, strTxState, - strMessageType, + strAddressType, getLockName, SEQUENCE_LOCK_TIME, ABS_LOCK_TIME, @@ -59,6 +59,12 @@ env = Environment(loader=PackageLoader('basicswap', 'templates')) env.filters['formatts'] = format_timestamp +def value_or_none(v): + if v == -1 or v == '-1': + return None + return v + + def getCoinName(c): if c == Coins.PART_ANON: return chainparams[Coins.PART]['name'].capitalize() + 'Anon' @@ -434,9 +440,15 @@ class HttpHandler(BaseHTTPRequestHandler): errors = [] parsed_data = {} + if have_data_entry(form_data, 'addr_to'): + page_data['addr_to'] = get_data_entry(form_data, 'addr_to') + addr_to = value_or_none(page_data['addr_to']) + if addr_to is not None: + parsed_data['addr_to'] = addr_to + if have_data_entry(form_data, 'addr_from'): page_data['addr_from'] = get_data_entry(form_data, 'addr_from') - parsed_data['addr_from'] = None if page_data['addr_from'] == '-1' else page_data['addr_from'] + parsed_data['addr_from'] = value_or_none(page_data['addr_from']) else: parsed_data['addr_from'] = None @@ -586,6 +598,9 @@ class HttpHandler(BaseHTTPRequestHandler): if 'valid_for_seconds' in parsed_data: extra_options['valid_for_seconds'] = parsed_data['valid_for_seconds'] + if 'addr_to' in parsed_data: + extra_options['addr_send_to'] = parsed_data['addr_to'] + offer_id = swap_client.postOffer( parsed_data['coin_from'], parsed_data['coin_to'], @@ -613,6 +628,7 @@ class HttpHandler(BaseHTTPRequestHandler): messages = [] page_data = { # Set defaults + 'addr_to': -1, 'fee_from_conf': 2, 'fee_to_conf': 2, 'validhrs': 1, @@ -649,7 +665,8 @@ class HttpHandler(BaseHTTPRequestHandler): h2=self.server.title, messages=messages, coins=listAvailableCoins(swap_client), - addrs=swap_client.listSmsgAddresses('offer'), + addrs=swap_client.listSmsgAddresses('offer_send_from'), + addrs_to=swap_client.listSmsgAddresses('offer_send_to'), data=page_data, form_id=os.urandom(8).hex(), ), 'UTF-8') @@ -714,6 +731,7 @@ class HttpHandler(BaseHTTPRequestHandler): 'lock_type': getLockName(offer.lock_type), 'lock_value': offer.lock_value, 'addr_from': offer.addr_from, + 'addr_to': 'Public' if offer.addr_to == swap_client.network_addr else offer.addr_to, 'created_at': offer.created_at, 'expired_at': offer.expire_at, 'sent': 'True' if offer.was_sent else 'False', @@ -800,7 +818,8 @@ class HttpHandler(BaseHTTPRequestHandler): ci_from.coin_name(), ci_to.coin_name(), ci_from.format_amount(o.amount_from), ci_to.format_amount((o.amount_from * o.rate) // ci_from.COIN()), - ci_to.format_amount(o.rate))) + ci_to.format_amount(o.rate), + 'Public' if o.addr_to == swap_client.network_addr else o.addr_to)) template = env.get_template('offers.html') return bytes(template.render( @@ -976,21 +995,34 @@ class HttpHandler(BaseHTTPRequestHandler): elif b'shownewaddr' in form_data: listaddresses = False page_data['new_address'] = True + elif b'showaddaddr' in form_data: + listaddresses = False + page_data['new_send_address'] = True elif b'createnewaddr' in form_data: addressnote = '' if b'addressnote' not in form_data else form_data[b'addressnote'][0].decode('utf-8') if not validateTextInput(addressnote, 'Address note', messages, max_length=30): listaddresses = False page_data['new_address'] = True else: - new_addr = swap_client.addSMSGAddress(addressnote=addressnote) - messages.append(f'Created address {new_addr}') + new_addr, pubkey = swap_client.newSMSGAddress(addressnote=addressnote) + messages.append(f'Created address {new_addr}, pubkey {pubkey}') + elif b'createnewsendaddr' in form_data: + pubkey_hex = form_data[b'addresspubkey'][0].decode('utf-8') + addressnote = '' if b'addressnote' not in form_data else form_data[b'addressnote'][0].decode('utf-8') + if not validateTextInput(addressnote, 'Address note', messages, max_length=30) or \ + not validateTextInput(pubkey_hex, 'Pubkey', messages, max_length=66): + listaddresses = False + page_data['new_send_address'] = True + else: + new_addr = swap_client.addSMSGAddress(pubkey_hex, addressnote=addressnote) + messages.append(f'Added address {new_addr}') if listaddresses is True: smsgaddresses = swap_client.listAllSMSGAddresses() network_addr = swap_client.network_addr for addr in smsgaddresses: - addr['type'] = strMessageType(addr['type']) + addr['type'] = strAddressType(addr['type']) template = env.get_template('smsgaddresses.html') return bytes(template.render( diff --git a/basicswap/interface_btc.py b/basicswap/interface_btc.py index 1963824..095e37d 100644 --- a/basicswap/interface_btc.py +++ b/basicswap/interface_btc.py @@ -13,6 +13,7 @@ from io import BytesIO from basicswap.contrib.test_framework import segwit_addr from .util import ( + b58encode, decodeScriptNum, getCompactSizeLen, SerialiseNumCompact, @@ -251,6 +252,13 @@ class BTCInterface(CoinInterface): pkh = hash160(pk) return segwit_addr.encode(bech32_prefix, version, pkh) + def pubkey_to_address(self, pk): + assert(len(pk) == 33) + prefix = chainparams[self.coin_type()][self._network]['pubkey_address'] + data = bytes((prefix,)) + hash160(pk) + checksum = hashlib.sha256(hashlib.sha256(data).digest()).digest() + return b58encode(data + checksum[0:4]) + def getNewSecretKey(self): return getSecretInt() diff --git a/basicswap/js_server.py b/basicswap/js_server.py index f879788..b7c2cf3 100644 --- a/basicswap/js_server.py +++ b/basicswap/js_server.py @@ -129,6 +129,8 @@ def js_offers(self, url_split, post_string, is_json, sent=False): ci_from = self.server.swap_client.ci(o.coin_from) ci_to = self.server.swap_client.ci(o.coin_to) rv.append({ + 'addr_from': o.addr_from, + 'addr_to': o.addr_to, 'offer_id': o.offer_id.hex(), 'created_at': o.created_at, 'expire_at': o.expire_at, @@ -136,7 +138,7 @@ def js_offers(self, url_split, post_string, is_json, sent=False): 'coin_to': ci_to.coin_name(), 'amount_from': ci_from.format_amount(o.amount_from), 'amount_to': ci_to.format_amount((o.amount_from * o.rate) // ci_from.COIN()), - 'rate': ci_to.format_amount(o.rate) + 'rate': ci_to.format_amount(o.rate), }) return bytes(json.dumps(rv), 'UTF-8') @@ -259,8 +261,13 @@ def js_smsgaddresses(self, url_split, post_string, is_json): post_data = urllib.parse.parse_qs(post_string) if url_split[3] == 'new': addressnote = get_data_entry_or(post_data, 'addressnote', '') - new_addr = swap_client.addSMSGAddress(addressnote) - return bytes(json.dumps({'new_address': new_addr}), 'UTF-8') + new_addr, pubkey = swap_client.newSMSGAddress(addressnote) + return bytes(json.dumps({'new_address': new_addr, 'pubkey': pubkey}), 'UTF-8') + if url_split[3] == 'add': + addressnote = get_data_entry_or(post_data, 'addressnote', '') + pubkey_hex = get_data_entry(post_data, 'addresspubkey') + added_address = swap_client.addSMSGAddress(pubkey_hex, addressnote) + return bytes(json.dumps({'added_address': added_address, 'pubkey': pubkey_hex}), 'UTF-8') elif url_split[3] == 'edit': address = get_data_entry(post_data, 'address') activeind = int(get_data_entry(post_data, 'active_ind')) diff --git a/basicswap/templates/offer.html b/basicswap/templates/offer.html index 3633cdf..3b8ea8a 100644 --- a/basicswap/templates/offer.html +++ b/basicswap/templates/offer.html @@ -22,6 +22,7 @@ Rate{{ data.rate }} {{ data.amt_from }}/{{ data.tla_from }} Script Lock Type{{ data.lock_type }} Script Lock Value{{ data.lock_value }} +Address To{{ data.addr_to }} Address From{{ data.addr_from }} Created At{{ data.created_at | formatts }} Expired At{{ data.expired_at | formatts }} diff --git a/basicswap/templates/offer_confirm.html b/basicswap/templates/offer_confirm.html index 068141c..ba75b9a 100644 --- a/basicswap/templates/offer_confirm.html +++ b/basicswap/templates/offer_confirm.html @@ -8,6 +8,12 @@
+
Send To
Send From Address + diff --git a/basicswap/templates/offer_new_1.html b/basicswap/templates/offer_new_1.html index 34b73d8..d64cc3f 100644 --- a/basicswap/templates/offer_new_1.html +++ b/basicswap/templates/offer_new_1.html @@ -8,6 +8,12 @@ +
Send To
Send From Address +
Send To
Send From Address + diff --git a/basicswap/templates/offers.html b/basicswap/templates/offers.html index 648960e..685c9a6 100644 --- a/basicswap/templates/offers.html +++ b/basicswap/templates/offers.html @@ -45,9 +45,9 @@ - + {% for o in offers %} - + {% endfor %}
AtOffer IDCoin FromCoin ToAmount FromAmount ToRate
AtRecipientOffer IDCoin FromCoin ToAmount FromAmount ToRate
{{ o[0] }}{{ o[1] }}{{ o[2] }}{{ o[3] }}{{ o[4] }}{{ o[5] }}{{ o[6] }}
{{ o[0] }}{{ o[7] }}{{ o[1] }}{{ o[2] }}{{ o[3] }}{{ o[4] }}{{ o[5] }}{{ o[6] }}
diff --git a/basicswap/templates/smsgaddresses.html b/basicswap/templates/smsgaddresses.html index 7e8efde..2142eaf 100644 --- a/basicswap/templates/smsgaddresses.html +++ b/basicswap/templates/smsgaddresses.html @@ -14,6 +14,7 @@

Edit Address {{ data.addr_data.addr }}

+
Pubkey{{ data.addr_data.pubkey }}
Active
{% elif data.new_address %} -

New Address

+

New Receiving Address

Note
+{% elif data.new_send_address %} +

Add Sending Address

+ + + + + +
Pubkey
Note
{% else %} @@ -39,6 +48,7 @@
AddressTypeActiveCreated AtNoteAction
+ {% endif %} diff --git a/tests/basicswap/test_other.py b/tests/basicswap/test_other.py index 9cb4a70..aa3f944 100644 --- a/tests/basicswap/test_other.py +++ b/tests/basicswap/test_other.py @@ -21,7 +21,7 @@ from coincurve.ecdsaotves import ( from coincurve.keys import ( PrivateKey) -from basicswap.ecc_util import i2b +from basicswap.ecc_util import i2b, h2b from basicswap.interface_btc import BTCInterface from basicswap.interface_xmr import XMRInterface @@ -206,6 +206,13 @@ class Test(unittest.TestCase): assert(len(sig) == 64) ci.verifyCompact(pk, 'test signing message', sig) + def test_pubkey_to_address(self): + coin_settings = {'rpcport': 0, 'rpcauth': 'none', 'blocks_confirmed': 1, 'conf_target': 1} + ci = BTCInterface(coin_settings, 'regtest') + pk = h2b('02c26a344e7d21bcc6f291532679559f2fd234c881271ff98714855edc753763a6') + addr = ci.pubkey_to_address(pk) + assert(addr == 'mj6SdSxmWRmdDqR5R3FfZmRiLmQfQAsLE8') + def test_dleag(self): coin_settings = {'rpcport': 0, 'walletrpcport': 0, 'walletrpcauth': 'none', 'blocks_confirmed': 1, 'conf_target': 1} ci = XMRInterface(coin_settings, 'regtest') diff --git a/tests/basicswap/test_xmr.py b/tests/basicswap/test_xmr.py index 6e63903..c69aa6e 100644 --- a/tests/basicswap/test_xmr.py +++ b/tests/basicswap/test_xmr.py @@ -466,8 +466,9 @@ class Test(unittest.TestCase): end_xmr = float(js_0_end['6']['balance']) + float(js_0_end['6']['unconfirmed']) assert(end_xmr > 10.9 and end_xmr < 11.0) - def test_011_smsgaddresses(self): + logging.info('---------- Test address management and private offers') + swap_clients = self.swap_clients js_1 = json.loads(urlopen('http://127.0.0.1:1801/json/smsgaddresses').read()) post_json = { @@ -475,6 +476,7 @@ class Test(unittest.TestCase): } json_rv = json.loads(post_json_req('http://127.0.0.1:1801/json/smsgaddresses/new', post_json)) new_address = json_rv['new_address'] + new_address_pk = json_rv['pubkey'] js_2 = json.loads(urlopen('http://127.0.0.1:1801/json/smsgaddresses').read()) assert(len(js_2) == len(js_1) + 1) @@ -534,6 +536,33 @@ class Test(unittest.TestCase): found = True assert(found is True) + post_json = { + 'addresspubkey': new_address_pk, + 'addressnote': 'testing_add_addr', + } + json_rv = json.loads(post_json_req('http://127.0.0.1:1800/json/smsgaddresses/add', post_json)) + assert(json_rv['added_address'] == new_address) + + post_json = { + 'addr_to': new_address, + 'addr_from': -1, + 'coin_from': 1, + 'coin_to': 6, + 'amt_from': 1, + 'amt_to': 1, + 'lockhrs': 24, + 'autoaccept': True} + rv = json.loads(post_json_req('http://127.0.0.1:1800/json/offers/new', post_json)) + offer_id_hex = rv['offer_id'] + + wait_for_offer(test_delay_event, swap_clients[1], bytes.fromhex(offer_id_hex)) + + rv = json.loads(urlopen(f'http://127.0.0.1:1801/json/offers/{offer_id_hex}').read()) + assert(rv[0]['addr_to'] == new_address) + + rv = json.loads(urlopen(f'http://127.0.0.1:1800/json/offers/{offer_id_hex}').read()) + assert(rv[0]['addr_to'] == new_address) + def test_02_leader_recover_a_lock_tx(self): logging.info('---------- Test PART to XMR leader recovers coin a lock tx') swap_clients = self.swap_clients