mirror of
https://github.com/basicswap/basicswap.git
synced 2025-01-05 10:19:25 +00:00
protocol: Enable private offers
Users can send private offers that will only be seen by one address. To send a private offer: 1. recipient creates a new address to receive offers on 2. recipient sends the pubkey for the newly created address to the offerer 3. offerer imports the recipient's pubkey 4. offerer sends a new offer to the recipients key instead of the public network Nodes will ignore offers sent on keys other than the network key or keys created for offer-receiving.
This commit is contained in:
parent
f63815b26b
commit
a40519737d
15 changed files with 217 additions and 38 deletions
|
@ -1,3 +1,3 @@
|
||||||
name = "basicswap"
|
name = "basicswap"
|
||||||
|
|
||||||
__version__ = "0.0.22"
|
__version__ = "0.0.23"
|
||||||
|
|
|
@ -99,6 +99,7 @@ from .basicswap_util import (
|
||||||
SEQUENCE_LOCK_TIME,
|
SEQUENCE_LOCK_TIME,
|
||||||
ABS_LOCK_BLOCKS,
|
ABS_LOCK_BLOCKS,
|
||||||
ABS_LOCK_TIME,
|
ABS_LOCK_TIME,
|
||||||
|
AddressTypes,
|
||||||
MessageTypes,
|
MessageTypes,
|
||||||
SwapTypes,
|
SwapTypes,
|
||||||
OfferStates,
|
OfferStates,
|
||||||
|
@ -119,6 +120,14 @@ from .basicswap_util import (
|
||||||
isActiveBidState)
|
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):
|
def threadPollChainState(swap_client, coin_type):
|
||||||
while not swap_client.delay_event.is_set():
|
while not swap_client.delay_event.is_set():
|
||||||
try:
|
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 active_ind INTEGER')
|
||||||
session.execute('ALTER TABLE smsgaddresses ADD COLUMN created_at 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 note VARCHAR')
|
||||||
|
session.execute('ALTER TABLE smsgaddresses ADD COLUMN pubkey VARCHAR')
|
||||||
session.execute('UPDATE smsgaddresses SET active_ind = 1, created_at = 1')
|
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
|
db_version += 1
|
||||||
|
|
||||||
if current_version != db_version:
|
if current_version != db_version:
|
||||||
|
@ -859,6 +872,11 @@ class BasicSwap(BaseApp):
|
||||||
if valid_for_seconds > 24 * 60 * 60:
|
if valid_for_seconds > 24 * 60 * 60:
|
||||||
raise ValueError('Bid TTL too high')
|
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,
|
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={}):
|
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
|
# 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.validateOfferLockValue(coin_from_t, coin_to_t, lock_type, lock_value)
|
||||||
self.validateOfferValidTime(swap_type, coin_from_t, coin_to_t, valid_for_seconds)
|
self.validateOfferValidTime(swap_type, coin_from_t, coin_to_t, valid_for_seconds)
|
||||||
|
|
||||||
|
offer_addr_to = self.getOfferAddressTo(extra_options)
|
||||||
|
|
||||||
self.mxDB.acquire()
|
self.mxDB.acquire()
|
||||||
session = None
|
session = None
|
||||||
try:
|
try:
|
||||||
|
@ -948,7 +968,7 @@ class BasicSwap(BaseApp):
|
||||||
self.callrpc('smsgaddlocaladdress', [offer_addr]) # Enable receiving smsg
|
self.callrpc('smsgaddlocaladdress', [offer_addr]) # Enable receiving smsg
|
||||||
options = {'decodehex': True, 'ttl_is_seconds': True}
|
options = {'decodehex': True, 'ttl_is_seconds': True}
|
||||||
msg_valid = max(self.SMSG_SECONDS_IN_HOUR * 1, valid_for_seconds)
|
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']
|
msg_id = ro['msgid']
|
||||||
|
|
||||||
offer_id = bytes.fromhex(msg_id)
|
offer_id = bytes.fromhex(msg_id)
|
||||||
|
@ -972,6 +992,7 @@ class BasicSwap(BaseApp):
|
||||||
lock_value=msg_buf.lock_value,
|
lock_value=msg_buf.lock_value,
|
||||||
swap_type=msg_buf.swap_type,
|
swap_type=msg_buf.swap_type,
|
||||||
|
|
||||||
|
addr_to=offer_addr_to,
|
||||||
addr_from=offer_addr,
|
addr_from=offer_addr,
|
||||||
created_at=offer_created_at,
|
created_at=offer_created_at,
|
||||||
expire_at=offer_created_at + msg_buf.time_valid,
|
expire_at=offer_created_at + msg_buf.time_valid,
|
||||||
|
@ -987,7 +1008,7 @@ class BasicSwap(BaseApp):
|
||||||
session.add(offer)
|
session.add(offer)
|
||||||
session.add(SentOffer(offer_id=offer_id))
|
session.add(SentOffer(offer_id=offer_id))
|
||||||
if addr_send_from is None:
|
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()
|
session.commit()
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
@ -1542,7 +1563,7 @@ class BasicSwap(BaseApp):
|
||||||
session = scoped_session(self.session_factory)
|
session = scoped_session(self.session_factory)
|
||||||
self.saveBidInSession(bid_id, bid, session)
|
self.saveBidInSession(bid_id, bid, session)
|
||||||
if addr_send_from is None:
|
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()
|
session.commit()
|
||||||
finally:
|
finally:
|
||||||
session.close()
|
session.close()
|
||||||
|
@ -1913,7 +1934,7 @@ class BasicSwap(BaseApp):
|
||||||
session = scoped_session(self.session_factory)
|
session = scoped_session(self.session_factory)
|
||||||
self.saveBidInSession(xmr_swap.bid_id, bid, session, xmr_swap)
|
self.saveBidInSession(xmr_swap.bid_id, bid, session, xmr_swap)
|
||||||
if addr_send_from is None:
|
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()
|
session.commit()
|
||||||
finally:
|
finally:
|
||||||
session.close()
|
session.close()
|
||||||
|
@ -3376,8 +3397,6 @@ class BasicSwap(BaseApp):
|
||||||
self.mxDB.release()
|
self.mxDB.release()
|
||||||
|
|
||||||
def processOffer(self, msg):
|
def processOffer(self, msg):
|
||||||
assert(msg['to'] == self.network_addr), 'Offer received on wrong address'
|
|
||||||
|
|
||||||
offer_bytes = bytes.fromhex(msg['hex'][2:-2])
|
offer_bytes = bytes.fromhex(msg['hex'][2:-2])
|
||||||
offer_data = OfferMessage()
|
offer_data = OfferMessage()
|
||||||
offer_data.ParseFromString(offer_bytes)
|
offer_data.ParseFromString(offer_bytes)
|
||||||
|
@ -3419,6 +3438,14 @@ class BasicSwap(BaseApp):
|
||||||
|
|
||||||
session = scoped_session(self.session_factory)
|
session = scoped_session(self.session_factory)
|
||||||
try:
|
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
|
# Check for sent
|
||||||
existing_offer = self.getOffer(offer_id)
|
existing_offer = self.getOffer(offer_id)
|
||||||
if existing_offer is None:
|
if existing_offer is None:
|
||||||
|
@ -3436,6 +3463,7 @@ class BasicSwap(BaseApp):
|
||||||
lock_value=offer_data.lock_value,
|
lock_value=offer_data.lock_value,
|
||||||
swap_type=offer_data.swap_type,
|
swap_type=offer_data.swap_type,
|
||||||
|
|
||||||
|
addr_to=msg['to'],
|
||||||
addr_from=msg['from'],
|
addr_from=msg['from'],
|
||||||
created_at=msg['sent'],
|
created_at=msg['sent'],
|
||||||
expire_at=msg['sent'] + offer_data.time_valid,
|
expire_at=msg['sent'] + offer_data.time_valid,
|
||||||
|
@ -3808,7 +3836,8 @@ class BasicSwap(BaseApp):
|
||||||
ci_from = self.ci(offer.coin_from)
|
ci_from = self.ci(offer.coin_from)
|
||||||
ci_to = self.ci(offer.coin_to)
|
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(msg['to'] == offer.addr_from), 'Received on incorrect address'
|
||||||
assert(now <= offer.expire_at), 'Offer expired'
|
assert(now <= offer.expire_at), 'Offer expired'
|
||||||
assert(bid_data.amount >= offer.min_bid_amount), 'Bid amount below minimum'
|
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)
|
kbsf = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 2, for_ed25519)
|
||||||
vkbs = ci_to.sumKeys(kbsl, kbsf)
|
vkbs = ci_to.sumKeys(kbsl, kbsf)
|
||||||
|
|
||||||
address_to = ci_to.getMainWalletAddress()
|
|
||||||
|
|
||||||
try:
|
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)
|
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.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)
|
self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_B_REFUND_TX_PUBLISHED, '', session)
|
||||||
|
@ -5054,7 +5082,7 @@ class BasicSwap(BaseApp):
|
||||||
try:
|
try:
|
||||||
session = scoped_session(self.session_factory)
|
session = scoped_session(self.session_factory)
|
||||||
rv = []
|
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)
|
q = session.execute(query_str)
|
||||||
for row in q:
|
for row in q:
|
||||||
|
@ -5065,6 +5093,7 @@ class BasicSwap(BaseApp):
|
||||||
'active_ind': row[3],
|
'active_ind': row[3],
|
||||||
'created_at': row[4],
|
'created_at': row[4],
|
||||||
'note': row[5],
|
'note': row[5],
|
||||||
|
'pubkey': row[6],
|
||||||
})
|
})
|
||||||
return rv
|
return rv
|
||||||
finally:
|
finally:
|
||||||
|
@ -5072,21 +5101,36 @@ class BasicSwap(BaseApp):
|
||||||
session.remove()
|
session.remove()
|
||||||
self.mxDB.release()
|
self.mxDB.release()
|
||||||
|
|
||||||
#listening_keys = self.callcoinrpc(Coins.PART, 'smsglocalkeys', [])
|
def newSMSGAddress(self, addressnote=None):
|
||||||
return []
|
|
||||||
|
|
||||||
def addSMSGAddress(self, addressnote=None):
|
|
||||||
# TODO: smsg addresses should be generated from a unique chain
|
# TODO: smsg addresses should be generated from a unique chain
|
||||||
self.mxDB.acquire()
|
self.mxDB.acquire()
|
||||||
try:
|
try:
|
||||||
session = scoped_session(self.session_factory)
|
session = scoped_session(self.session_factory)
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
new_addr = self.callrpc('getnewaddress')
|
new_addr = self.callrpc('getnewaddress')
|
||||||
|
addr_info = self.callrpc('getaddressinfo', [new_addr])
|
||||||
self.callrpc('smsgaddlocaladdress', [new_addr]) # Enable receiving smsgs
|
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()
|
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:
|
finally:
|
||||||
session.close()
|
session.close()
|
||||||
session.remove()
|
session.remove()
|
||||||
|
@ -5107,7 +5151,15 @@ class BasicSwap(BaseApp):
|
||||||
self.mxDB.release()
|
self.mxDB.release()
|
||||||
|
|
||||||
def listSmsgAddresses(self, use_type_str):
|
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()
|
self.mxDB.acquire()
|
||||||
try:
|
try:
|
||||||
session = scoped_session(self.session_factory)
|
session = scoped_session(self.session_factory)
|
||||||
|
|
|
@ -38,6 +38,13 @@ class MessageTypes(IntEnum):
|
||||||
OFFER_REVOKE = auto()
|
OFFER_REVOKE = auto()
|
||||||
|
|
||||||
|
|
||||||
|
class AddressTypes(IntEnum):
|
||||||
|
OFFER = auto()
|
||||||
|
BID = auto()
|
||||||
|
RECV_OFFER = auto()
|
||||||
|
SEND_OFFER = auto()
|
||||||
|
|
||||||
|
|
||||||
class SwapTypes(IntEnum):
|
class SwapTypes(IntEnum):
|
||||||
SELLER_FIRST = auto()
|
SELLER_FIRST = auto()
|
||||||
BUYER_FIRST = auto()
|
BUYER_FIRST = auto()
|
||||||
|
@ -239,11 +246,15 @@ def strTxType(tx_type):
|
||||||
return 'Unknown'
|
return 'Unknown'
|
||||||
|
|
||||||
|
|
||||||
def strMessageType(msg_type):
|
def strAddressType(addr_type):
|
||||||
if msg_type == MessageTypes.OFFER:
|
if addr_type == AddressTypes.OFFER:
|
||||||
return 'Offers'
|
return 'Offer'
|
||||||
if msg_type == MessageTypes.BID:
|
if addr_type == AddressTypes.BID:
|
||||||
return 'Bids'
|
return 'Bid'
|
||||||
|
if addr_type == AddressTypes.RECV_OFFER:
|
||||||
|
return 'Offer recv'
|
||||||
|
if addr_type == AddressTypes.SEND_OFFER:
|
||||||
|
return 'Offer send'
|
||||||
return 'Unknown'
|
return 'Unknown'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ class Offer(Base):
|
||||||
secret_hash = sa.Column(sa.LargeBinary)
|
secret_hash = sa.Column(sa.LargeBinary)
|
||||||
|
|
||||||
addr_from = sa.Column(sa.String)
|
addr_from = sa.Column(sa.String)
|
||||||
|
addr_to = sa.Column(sa.String)
|
||||||
created_at = sa.Column(sa.BigInteger)
|
created_at = sa.Column(sa.BigInteger)
|
||||||
expire_at = sa.Column(sa.BigInteger)
|
expire_at = sa.Column(sa.BigInteger)
|
||||||
was_sent = sa.Column(sa.Boolean)
|
was_sent = sa.Column(sa.Boolean)
|
||||||
|
@ -218,6 +219,7 @@ class SmsgAddress(Base):
|
||||||
active_ind = sa.Column(sa.Integer)
|
active_ind = sa.Column(sa.Integer)
|
||||||
created_at = sa.Column(sa.BigInteger)
|
created_at = sa.Column(sa.BigInteger)
|
||||||
addr = sa.Column(sa.String, unique=True)
|
addr = sa.Column(sa.String, unique=True)
|
||||||
|
pubkey = sa.Column(sa.String)
|
||||||
use_type = sa.Column(sa.Integer)
|
use_type = sa.Column(sa.Integer)
|
||||||
note = sa.Column(sa.String)
|
note = sa.Column(sa.String)
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ from .basicswap_util import (
|
||||||
strOfferState,
|
strOfferState,
|
||||||
strBidState,
|
strBidState,
|
||||||
strTxState,
|
strTxState,
|
||||||
strMessageType,
|
strAddressType,
|
||||||
getLockName,
|
getLockName,
|
||||||
SEQUENCE_LOCK_TIME,
|
SEQUENCE_LOCK_TIME,
|
||||||
ABS_LOCK_TIME,
|
ABS_LOCK_TIME,
|
||||||
|
@ -59,6 +59,12 @@ env = Environment(loader=PackageLoader('basicswap', 'templates'))
|
||||||
env.filters['formatts'] = format_timestamp
|
env.filters['formatts'] = format_timestamp
|
||||||
|
|
||||||
|
|
||||||
|
def value_or_none(v):
|
||||||
|
if v == -1 or v == '-1':
|
||||||
|
return None
|
||||||
|
return v
|
||||||
|
|
||||||
|
|
||||||
def getCoinName(c):
|
def getCoinName(c):
|
||||||
if c == Coins.PART_ANON:
|
if c == Coins.PART_ANON:
|
||||||
return chainparams[Coins.PART]['name'].capitalize() + 'Anon'
|
return chainparams[Coins.PART]['name'].capitalize() + 'Anon'
|
||||||
|
@ -434,9 +440,15 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||||
errors = []
|
errors = []
|
||||||
parsed_data = {}
|
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'):
|
if have_data_entry(form_data, 'addr_from'):
|
||||||
page_data['addr_from'] = get_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:
|
else:
|
||||||
parsed_data['addr_from'] = None
|
parsed_data['addr_from'] = None
|
||||||
|
|
||||||
|
@ -586,6 +598,9 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||||
if 'valid_for_seconds' in parsed_data:
|
if 'valid_for_seconds' in parsed_data:
|
||||||
extra_options['valid_for_seconds'] = parsed_data['valid_for_seconds']
|
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(
|
offer_id = swap_client.postOffer(
|
||||||
parsed_data['coin_from'],
|
parsed_data['coin_from'],
|
||||||
parsed_data['coin_to'],
|
parsed_data['coin_to'],
|
||||||
|
@ -613,6 +628,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||||
messages = []
|
messages = []
|
||||||
page_data = {
|
page_data = {
|
||||||
# Set defaults
|
# Set defaults
|
||||||
|
'addr_to': -1,
|
||||||
'fee_from_conf': 2,
|
'fee_from_conf': 2,
|
||||||
'fee_to_conf': 2,
|
'fee_to_conf': 2,
|
||||||
'validhrs': 1,
|
'validhrs': 1,
|
||||||
|
@ -649,7 +665,8 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||||
h2=self.server.title,
|
h2=self.server.title,
|
||||||
messages=messages,
|
messages=messages,
|
||||||
coins=listAvailableCoins(swap_client),
|
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,
|
data=page_data,
|
||||||
form_id=os.urandom(8).hex(),
|
form_id=os.urandom(8).hex(),
|
||||||
), 'UTF-8')
|
), 'UTF-8')
|
||||||
|
@ -714,6 +731,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||||
'lock_type': getLockName(offer.lock_type),
|
'lock_type': getLockName(offer.lock_type),
|
||||||
'lock_value': offer.lock_value,
|
'lock_value': offer.lock_value,
|
||||||
'addr_from': offer.addr_from,
|
'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,
|
'created_at': offer.created_at,
|
||||||
'expired_at': offer.expire_at,
|
'expired_at': offer.expire_at,
|
||||||
'sent': 'True' if offer.was_sent else 'False',
|
'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.coin_name(), ci_to.coin_name(),
|
||||||
ci_from.format_amount(o.amount_from),
|
ci_from.format_amount(o.amount_from),
|
||||||
ci_to.format_amount((o.amount_from * o.rate) // ci_from.COIN()),
|
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')
|
template = env.get_template('offers.html')
|
||||||
return bytes(template.render(
|
return bytes(template.render(
|
||||||
|
@ -976,21 +995,34 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||||
elif b'shownewaddr' in form_data:
|
elif b'shownewaddr' in form_data:
|
||||||
listaddresses = False
|
listaddresses = False
|
||||||
page_data['new_address'] = True
|
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:
|
elif b'createnewaddr' in form_data:
|
||||||
addressnote = '' if b'addressnote' not in form_data else form_data[b'addressnote'][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):
|
if not validateTextInput(addressnote, 'Address note', messages, max_length=30):
|
||||||
listaddresses = False
|
listaddresses = False
|
||||||
page_data['new_address'] = True
|
page_data['new_address'] = True
|
||||||
else:
|
else:
|
||||||
new_addr = swap_client.addSMSGAddress(addressnote=addressnote)
|
new_addr, pubkey = swap_client.newSMSGAddress(addressnote=addressnote)
|
||||||
messages.append(f'Created address {new_addr}')
|
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:
|
if listaddresses is True:
|
||||||
smsgaddresses = swap_client.listAllSMSGAddresses()
|
smsgaddresses = swap_client.listAllSMSGAddresses()
|
||||||
network_addr = swap_client.network_addr
|
network_addr = swap_client.network_addr
|
||||||
|
|
||||||
for addr in smsgaddresses:
|
for addr in smsgaddresses:
|
||||||
addr['type'] = strMessageType(addr['type'])
|
addr['type'] = strAddressType(addr['type'])
|
||||||
|
|
||||||
template = env.get_template('smsgaddresses.html')
|
template = env.get_template('smsgaddresses.html')
|
||||||
return bytes(template.render(
|
return bytes(template.render(
|
||||||
|
|
|
@ -13,6 +13,7 @@ from io import BytesIO
|
||||||
from basicswap.contrib.test_framework import segwit_addr
|
from basicswap.contrib.test_framework import segwit_addr
|
||||||
|
|
||||||
from .util import (
|
from .util import (
|
||||||
|
b58encode,
|
||||||
decodeScriptNum,
|
decodeScriptNum,
|
||||||
getCompactSizeLen,
|
getCompactSizeLen,
|
||||||
SerialiseNumCompact,
|
SerialiseNumCompact,
|
||||||
|
@ -251,6 +252,13 @@ class BTCInterface(CoinInterface):
|
||||||
pkh = hash160(pk)
|
pkh = hash160(pk)
|
||||||
return segwit_addr.encode(bech32_prefix, version, pkh)
|
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):
|
def getNewSecretKey(self):
|
||||||
return getSecretInt()
|
return getSecretInt()
|
||||||
|
|
||||||
|
|
|
@ -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_from = self.server.swap_client.ci(o.coin_from)
|
||||||
ci_to = self.server.swap_client.ci(o.coin_to)
|
ci_to = self.server.swap_client.ci(o.coin_to)
|
||||||
rv.append({
|
rv.append({
|
||||||
|
'addr_from': o.addr_from,
|
||||||
|
'addr_to': o.addr_to,
|
||||||
'offer_id': o.offer_id.hex(),
|
'offer_id': o.offer_id.hex(),
|
||||||
'created_at': o.created_at,
|
'created_at': o.created_at,
|
||||||
'expire_at': o.expire_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(),
|
'coin_to': ci_to.coin_name(),
|
||||||
'amount_from': ci_from.format_amount(o.amount_from),
|
'amount_from': ci_from.format_amount(o.amount_from),
|
||||||
'amount_to': ci_to.format_amount((o.amount_from * o.rate) // ci_from.COIN()),
|
'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')
|
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)
|
post_data = urllib.parse.parse_qs(post_string)
|
||||||
if url_split[3] == 'new':
|
if url_split[3] == 'new':
|
||||||
addressnote = get_data_entry_or(post_data, 'addressnote', '')
|
addressnote = get_data_entry_or(post_data, 'addressnote', '')
|
||||||
new_addr = swap_client.addSMSGAddress(addressnote)
|
new_addr, pubkey = swap_client.newSMSGAddress(addressnote)
|
||||||
return bytes(json.dumps({'new_address': new_addr}), 'UTF-8')
|
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':
|
elif url_split[3] == 'edit':
|
||||||
address = get_data_entry(post_data, 'address')
|
address = get_data_entry(post_data, 'address')
|
||||||
activeind = int(get_data_entry(post_data, 'active_ind'))
|
activeind = int(get_data_entry(post_data, 'active_ind'))
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
<tr><td>Rate</td><td>{{ data.rate }} {{ data.amt_from }}/{{ data.tla_from }}</td></tr>
|
<tr><td>Rate</td><td>{{ data.rate }} {{ data.amt_from }}/{{ data.tla_from }}</td></tr>
|
||||||
<tr><td>Script Lock Type</td><td>{{ data.lock_type }}</td></tr>
|
<tr><td>Script Lock Type</td><td>{{ data.lock_type }}</td></tr>
|
||||||
<tr><td>Script Lock Value</td><td>{{ data.lock_value }}</td></tr>
|
<tr><td>Script Lock Value</td><td>{{ data.lock_value }}</td></tr>
|
||||||
|
<tr><td>Address To</td><td>{{ data.addr_to }}</td></tr>
|
||||||
<tr><td>Address From</td><td>{{ data.addr_from }}</td></tr>
|
<tr><td>Address From</td><td>{{ data.addr_from }}</td></tr>
|
||||||
<tr><td>Created At</td><td>{{ data.created_at | formatts }}</td></tr>
|
<tr><td>Created At</td><td>{{ data.created_at | formatts }}</td></tr>
|
||||||
<tr><td>Expired At</td><td>{{ data.expired_at | formatts }}</td></tr>
|
<tr><td>Expired At</td><td>{{ data.expired_at | formatts }}</td></tr>
|
||||||
|
|
|
@ -8,6 +8,12 @@
|
||||||
<form method="post">
|
<form method="post">
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
<tr><td>Send To</td><td><select name="addr_to_" disabled>
|
||||||
|
<option{% if data.addr_to=="-1" %} selected{% endif %} value="-1">-- Public Network --</option>
|
||||||
|
{% for a in addrs_to %}
|
||||||
|
<option{% if data.addr_to==a %} selected{% endif %} value="{{ a }}">{{ a }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select></td></tr>
|
||||||
<tr><td>Send From Address</td><td><select name="addr_from_" disabled>
|
<tr><td>Send From Address</td><td><select name="addr_from_" disabled>
|
||||||
{% for a in addrs %}
|
{% for a in addrs %}
|
||||||
<option{% if data.addr_from==a %} selected{% endif %} value="{{ a }}">{{ a }}</option>
|
<option{% if data.addr_from==a %} selected{% endif %} value="{{ a }}">{{ a }}</option>
|
||||||
|
@ -62,6 +68,7 @@
|
||||||
<input name="submit_offer" type="submit" value="Confirm Offer">
|
<input name="submit_offer" type="submit" value="Confirm Offer">
|
||||||
<input name="step2" type="submit" value="Back">
|
<input name="step2" type="submit" value="Back">
|
||||||
<input type="hidden" name="formid" value="{{ form_id }}">
|
<input type="hidden" name="formid" value="{{ form_id }}">
|
||||||
|
<input type="hidden" name="addr_to" value="{{ data.addr_to }}">
|
||||||
<input type="hidden" name="addr_from" value="{{ data.addr_from }}">
|
<input type="hidden" name="addr_from" value="{{ data.addr_from }}">
|
||||||
<input type="hidden" name="coin_from" value="{{ data.coin_from }}">
|
<input type="hidden" name="coin_from" value="{{ data.coin_from }}">
|
||||||
<input type="hidden" name="fee_from_extra" value="{{ data.fee_from_extra }}">
|
<input type="hidden" name="fee_from_extra" value="{{ data.fee_from_extra }}">
|
||||||
|
|
|
@ -8,6 +8,12 @@
|
||||||
<form method="post">
|
<form method="post">
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
<tr><td>Send To</td><td><select name="addr_to">
|
||||||
|
<option{% if data.addr_to=="-1" %} selected{% endif %} value="-1">-- Public Network --</option>
|
||||||
|
{% for a in addrs_to %}
|
||||||
|
<option{% if data.addr_to==a %} selected{% endif %} value="{{ a }}">{{ a }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select></td></tr>
|
||||||
<tr><td>Send From Address</td><td><select name="addr_from">
|
<tr><td>Send From Address</td><td><select name="addr_from">
|
||||||
{% for a in addrs %}
|
{% for a in addrs %}
|
||||||
<option{% if data.addr_from==a %} selected{% endif %} value="{{ a }}">{{ a }}</option>
|
<option{% if data.addr_from==a %} selected{% endif %} value="{{ a }}">{{ a }}</option>
|
||||||
|
|
|
@ -8,6 +8,12 @@
|
||||||
<form method="post">
|
<form method="post">
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
<tr><td>Send To</td><td><select name="addr_to_" disabled>
|
||||||
|
<option{% if data.addr_to=="-1" %} selected{% endif %} value="-1">-- Public Network --</option>
|
||||||
|
{% for a in addrs_to %}
|
||||||
|
<option{% if data.addr_to==a %} selected{% endif %} value="{{ a }}">{{ a }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select></td></tr>
|
||||||
<tr><td>Send From Address</td><td><select name="addr_from_" disabled>
|
<tr><td>Send From Address</td><td><select name="addr_from_" disabled>
|
||||||
{% for a in addrs %}
|
{% for a in addrs %}
|
||||||
<option{% if data.addr_from==a %} selected{% endif %} value="{{ a }}">{{ a }}</option>
|
<option{% if data.addr_from==a %} selected{% endif %} value="{{ a }}">{{ a }}</option>
|
||||||
|
@ -59,6 +65,7 @@
|
||||||
<input name="check_offer" type="submit" value="Continue">
|
<input name="check_offer" type="submit" value="Continue">
|
||||||
<input name="step1" type="submit" value="Back">
|
<input name="step1" type="submit" value="Back">
|
||||||
<input type="hidden" name="formid" value="{{ form_id }}">
|
<input type="hidden" name="formid" value="{{ form_id }}">
|
||||||
|
<input type="hidden" name="addr_to" value="{{ data.addr_to }}">
|
||||||
<input type="hidden" name="addr_from" value="{{ data.addr_from }}">
|
<input type="hidden" name="addr_from" value="{{ data.addr_from }}">
|
||||||
<input type="hidden" name="coin_from" value="{{ data.coin_from }}">
|
<input type="hidden" name="coin_from" value="{{ data.coin_from }}">
|
||||||
<input type="hidden" name="coin_to" value="{{ data.coin_to }}">
|
<input type="hidden" name="coin_to" value="{{ data.coin_to }}">
|
||||||
|
|
|
@ -45,9 +45,9 @@
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr><th>At</th><th>Offer ID</th><th>Coin From</th><th>Coin To</th><th>Amount From</th><th>Amount To</th><th>Rate</th></tr>
|
<tr><th>At</th><th>Recipient</th><th>Offer ID</th><th>Coin From</th><th>Coin To</th><th>Amount From</th><th>Amount To</th><th>Rate</th></tr>
|
||||||
{% for o in offers %}
|
{% for o in offers %}
|
||||||
<tr><td>{{ o[0] }}</td><td><a href=/offer/{{ o[1] }}>{{ o[1] }}</a></td><td>{{ o[2] }}</td><td>{{ o[3] }}</td><td>{{ o[4] }}</td><td>{{ o[5] }}</td><td>{{ o[6] }}</td></tr>
|
<tr><td>{{ o[0] }}</td><td>{{ o[7] }}</td><td><a href=/offer/{{ o[1] }}>{{ o[1] }}</a></td><td>{{ o[2] }}</td><td>{{ o[3] }}</td><td>{{ o[4] }}</td><td>{{ o[5] }}</td><td>{{ o[6] }}</td></tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
<br/><h4>Edit Address {{ data.addr_data.addr }}</h4>
|
<br/><h4>Edit Address {{ data.addr_data.addr }}</h4>
|
||||||
<table>
|
<table>
|
||||||
|
<tr><td>Pubkey</td><td>{{ data.addr_data.pubkey }}</td></tr>
|
||||||
<tr><td>Active</td><td><select name="active_ind">
|
<tr><td>Active</td><td><select name="active_ind">
|
||||||
<option value="1"{% if data.addr_data.active_ind==1 %} selected{% endif %}>True</option>
|
<option value="1"{% if data.addr_data.active_ind==1 %} selected{% endif %}>True</option>
|
||||||
<option value="0"{% if data.addr_data.active_ind==0 %} selected{% endif %}>False</option>
|
<option value="0"{% if data.addr_data.active_ind==0 %} selected{% endif %}>False</option>
|
||||||
|
@ -23,12 +24,20 @@
|
||||||
<tr><td><input type="submit" name="saveaddr" value="Save Address"><input type="submit" name="cancel" value="Cancel"></td></tr>
|
<tr><td><input type="submit" name="saveaddr" value="Save Address"><input type="submit" name="cancel" value="Cancel"></td></tr>
|
||||||
</table>
|
</table>
|
||||||
{% elif data.new_address %}
|
{% elif data.new_address %}
|
||||||
<br/><h4>New Address</h4>
|
<br/><h4>New Receiving Address</h4>
|
||||||
<table>
|
<table>
|
||||||
<tr><td>Note</td><td><input name="addressnote" type="text" value="" maxlength="30"></td></tr>
|
<tr><td>Note</td><td><input name="addressnote" type="text" value="" maxlength="30"></td></tr>
|
||||||
|
|
||||||
<tr><td><input type="submit" name="createnewaddr" value="Create Address"><input type="submit" name="cancel" value="Cancel"></td></tr>
|
<tr><td><input type="submit" name="createnewaddr" value="Create Address"><input type="submit" name="cancel" value="Cancel"></td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
{% elif data.new_send_address %}
|
||||||
|
<br/><h4>Add Sending Address</h4>
|
||||||
|
<table>
|
||||||
|
<tr><td>Pubkey</td><td><input name="addresspubkey" type="text" value="" maxlength="66"></td></tr>
|
||||||
|
<tr><td>Note</td><td><input name="addressnote" type="text" value="" maxlength="30"></td></tr>
|
||||||
|
|
||||||
|
<tr><td><input type="submit" name="createnewsendaddr" value="Add Address"><input type="submit" name="cancel" value="Cancel"></td></tr>
|
||||||
|
</table>
|
||||||
{% else %}
|
{% else %}
|
||||||
<table>
|
<table>
|
||||||
<tr><th>Address</th><th>Type</th><th>Active</th><th>Created At</th><th>Note</th><th>Action</th></tr>
|
<tr><th>Address</th><th>Type</th><th>Active</th><th>Created At</th><th>Note</th><th>Action</th></tr>
|
||||||
|
@ -39,6 +48,7 @@
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<input type="submit" name="shownewaddr" value="New Address">
|
<input type="submit" name="shownewaddr" value="New Address">
|
||||||
|
<input type="submit" name="showaddaddr" value="Add Sending Address">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<input type="hidden" name="formid" value="{{ form_id }}">
|
<input type="hidden" name="formid" value="{{ form_id }}">
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -21,7 +21,7 @@ from coincurve.ecdsaotves import (
|
||||||
from coincurve.keys import (
|
from coincurve.keys import (
|
||||||
PrivateKey)
|
PrivateKey)
|
||||||
|
|
||||||
from basicswap.ecc_util import i2b
|
from basicswap.ecc_util import i2b, h2b
|
||||||
from basicswap.interface_btc import BTCInterface
|
from basicswap.interface_btc import BTCInterface
|
||||||
from basicswap.interface_xmr import XMRInterface
|
from basicswap.interface_xmr import XMRInterface
|
||||||
|
|
||||||
|
@ -206,6 +206,13 @@ class Test(unittest.TestCase):
|
||||||
assert(len(sig) == 64)
|
assert(len(sig) == 64)
|
||||||
ci.verifyCompact(pk, 'test signing message', sig)
|
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):
|
def test_dleag(self):
|
||||||
coin_settings = {'rpcport': 0, 'walletrpcport': 0, 'walletrpcauth': 'none', 'blocks_confirmed': 1, 'conf_target': 1}
|
coin_settings = {'rpcport': 0, 'walletrpcport': 0, 'walletrpcauth': 'none', 'blocks_confirmed': 1, 'conf_target': 1}
|
||||||
ci = XMRInterface(coin_settings, 'regtest')
|
ci = XMRInterface(coin_settings, 'regtest')
|
||||||
|
|
|
@ -466,8 +466,9 @@ class Test(unittest.TestCase):
|
||||||
end_xmr = float(js_0_end['6']['balance']) + float(js_0_end['6']['unconfirmed'])
|
end_xmr = float(js_0_end['6']['balance']) + float(js_0_end['6']['unconfirmed'])
|
||||||
assert(end_xmr > 10.9 and end_xmr < 11.0)
|
assert(end_xmr > 10.9 and end_xmr < 11.0)
|
||||||
|
|
||||||
|
|
||||||
def test_011_smsgaddresses(self):
|
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())
|
js_1 = json.loads(urlopen('http://127.0.0.1:1801/json/smsgaddresses').read())
|
||||||
|
|
||||||
post_json = {
|
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))
|
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 = json_rv['new_address']
|
||||||
|
new_address_pk = json_rv['pubkey']
|
||||||
|
|
||||||
js_2 = json.loads(urlopen('http://127.0.0.1:1801/json/smsgaddresses').read())
|
js_2 = json.loads(urlopen('http://127.0.0.1:1801/json/smsgaddresses').read())
|
||||||
assert(len(js_2) == len(js_1) + 1)
|
assert(len(js_2) == len(js_1) + 1)
|
||||||
|
@ -534,6 +536,33 @@ class Test(unittest.TestCase):
|
||||||
found = True
|
found = True
|
||||||
assert(found is 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):
|
def test_02_leader_recover_a_lock_tx(self):
|
||||||
logging.info('---------- Test PART to XMR leader recovers coin a lock tx')
|
logging.info('---------- Test PART to XMR leader recovers coin a lock tx')
|
||||||
swap_clients = self.swap_clients
|
swap_clients = self.swap_clients
|
||||||
|
|
Loading…
Reference in a new issue