Lint fixes and multiple bids test.
This commit is contained in:
parent
4913ac7a2b
commit
7f4be161d7
@ -48,7 +48,7 @@ jobs:
|
|||||||
before_script:
|
before_script:
|
||||||
script:
|
script:
|
||||||
- PYTHONWARNINGS="ignore" flake8 --ignore=E501,F841,W503 --exclude=basicswap/contrib,messages_pb2.py,.eggs
|
- PYTHONWARNINGS="ignore" flake8 --ignore=E501,F841,W503 --exclude=basicswap/contrib,messages_pb2.py,.eggs
|
||||||
- codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=tests/lint/spelling.ignore-words.txt -S .git,.eggs,gitianpubkeys,*.pyc,basicswap/contrib
|
- codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=tests/lint/spelling.ignore-words.txt -S .git,.eggs,gitianpubkeys,*.pyc,*basicswap/contrib,*mnemonics.py
|
||||||
after_success:
|
after_success:
|
||||||
- echo "End lint"
|
- echo "End lint"
|
||||||
- stage: test
|
- stage: test
|
||||||
|
@ -41,7 +41,6 @@ from .util import (
|
|||||||
toWIF,
|
toWIF,
|
||||||
getKeyID,
|
getKeyID,
|
||||||
make_int,
|
make_int,
|
||||||
dumpj
|
|
||||||
)
|
)
|
||||||
from .chainparams import (
|
from .chainparams import (
|
||||||
chainparams,
|
chainparams,
|
||||||
@ -81,8 +80,6 @@ from .db import (
|
|||||||
from .explorers import ExplorerInsight, ExplorerBitAps, ExplorerChainz
|
from .explorers import ExplorerInsight, ExplorerBitAps, ExplorerChainz
|
||||||
import basicswap.config as cfg
|
import basicswap.config as cfg
|
||||||
from .base import BaseApp
|
from .base import BaseApp
|
||||||
from .ecc_util import (
|
|
||||||
b2i, i2b)
|
|
||||||
|
|
||||||
|
|
||||||
MIN_OFFER_VALID_TIME = 60 * 10
|
MIN_OFFER_VALID_TIME = 60 * 10
|
||||||
@ -359,7 +356,7 @@ class WatchedOutput():
|
|||||||
|
|
||||||
|
|
||||||
class WatchedTransaction():
|
class WatchedTransaction():
|
||||||
# Watch for presense in mempool (getrawtransaction)
|
# Watch for presence in mempool (getrawtransaction)
|
||||||
def __init__(self, bid_id, txid_hex, tx_type, swap_type):
|
def __init__(self, bid_id, txid_hex, tx_type, swap_type):
|
||||||
self.bid_id = bid_id
|
self.bid_id = bid_id
|
||||||
self.txid_hex = txid_hex
|
self.txid_hex = txid_hex
|
||||||
@ -1281,7 +1278,7 @@ class BasicSwap(BaseApp):
|
|||||||
bid.xmr_b_lock_tx = stx
|
bid.xmr_b_lock_tx = stx
|
||||||
else:
|
else:
|
||||||
bid.txns[stx.tx_type] = stx
|
bid.txns[stx.tx_type] = stx
|
||||||
#self.log.warning('Unknown transaction type: {}'.format(stx.tx_type))
|
|
||||||
def getXmrBid(self, bid_id, sent=False):
|
def getXmrBid(self, bid_id, sent=False):
|
||||||
self.mxDB.acquire()
|
self.mxDB.acquire()
|
||||||
try:
|
try:
|
||||||
@ -1524,14 +1521,10 @@ class BasicSwap(BaseApp):
|
|||||||
ro = self.callrpc('smsgsend', [bid_addr, offer.addr_from, payload_hex, False, msg_valid, False, options])
|
ro = self.callrpc('smsgsend', [bid_addr, offer.addr_from, payload_hex, False, msg_valid, False, options])
|
||||||
xmr_swap.bid_msg_id3 = bytes.fromhex(ro['msgid'])
|
xmr_swap.bid_msg_id3 = bytes.fromhex(ro['msgid'])
|
||||||
|
|
||||||
|
|
||||||
bid = Bid(
|
bid = Bid(
|
||||||
bid_id=xmr_swap.bid_id,
|
bid_id=xmr_swap.bid_id,
|
||||||
offer_id=offer_id,
|
offer_id=offer_id,
|
||||||
amount=msg_buf.amount,
|
amount=msg_buf.amount,
|
||||||
#pkhash_buyer=msg_buf.pkhash_buyer,
|
|
||||||
#proof_address=msg_buf.proof_address,
|
|
||||||
|
|
||||||
created_at=bid_created_at,
|
created_at=bid_created_at,
|
||||||
contract_count=xmr_swap.contract_count,
|
contract_count=xmr_swap.contract_count,
|
||||||
amount_to=(msg_buf.amount * offer.rate) // COIN,
|
amount_to=(msg_buf.amount * offer.rate) // COIN,
|
||||||
@ -2358,22 +2351,19 @@ class BasicSwap(BaseApp):
|
|||||||
delay = random.randrange(self.min_delay_auto_accept, self.max_delay_auto_accept)
|
delay = random.randrange(self.min_delay_auto_accept, self.max_delay_auto_accept)
|
||||||
self.log.info('Sending xmr swap chain B lock tx for bid %s in %d seconds', bid_id.hex(), delay)
|
self.log.info('Sending xmr swap chain B lock tx for bid %s in %d seconds', bid_id.hex(), delay)
|
||||||
self.createEventInSession(delay, EventTypes.SEND_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
self.createEventInSession(delay, EventTypes.SEND_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||||
#bid.setState(BidStates.SWAP_DELAYING)
|
# bid.setState(BidStates.SWAP_DELAYING)
|
||||||
|
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
elif state == BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED:
|
elif state == BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED:
|
||||||
#if bid.was_sent and TxTypes.XMR_SWAP_B_LOCK not in bid.txns:
|
|
||||||
if bid.was_sent and bid.xmr_b_lock_tx is None:
|
if bid.was_sent and bid.xmr_b_lock_tx is None:
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
found_tx = ci_to.findTxB(xmr_swap.vkbv, xmr_swap.pkbs, bid.amount_to, ci_to.blocks_confirmed, xmr_swap.b_restore_height)
|
found_tx = ci_to.findTxB(xmr_swap.vkbv, xmr_swap.pkbs, bid.amount_to, ci_to.blocks_confirmed, xmr_swap.b_restore_height)
|
||||||
if found_tx is not None:
|
if found_tx is not None:
|
||||||
|
|
||||||
#if TxTypes.XMR_SWAP_B_LOCK not in bid.txns:
|
|
||||||
if bid.xmr_b_lock_tx is None:
|
if bid.xmr_b_lock_tx is None:
|
||||||
b_lock_tx_id = bytes.fromhex(found_tx['txid'])
|
b_lock_tx_id = bytes.fromhex(found_tx['txid'])
|
||||||
#bid.txns[TxTypes.XMR_SWAP_B_LOCK] = SwapTx(
|
|
||||||
bid.xmr_b_lock_tx = SwapTx(
|
bid.xmr_b_lock_tx = SwapTx(
|
||||||
bid_id=bid_id,
|
bid_id=bid_id,
|
||||||
tx_type=TxTypes.XMR_SWAP_B_LOCK,
|
tx_type=TxTypes.XMR_SWAP_B_LOCK,
|
||||||
@ -2400,7 +2390,6 @@ class BasicSwap(BaseApp):
|
|||||||
# TODO: Use explorer to get tx / block hash for getrawtransaction
|
# TODO: Use explorer to get tx / block hash for getrawtransaction
|
||||||
pass
|
pass
|
||||||
elif state == BidStates.XMR_SWAP_SCRIPT_TX_REDEEMED:
|
elif state == BidStates.XMR_SWAP_SCRIPT_TX_REDEEMED:
|
||||||
#txid_hex = bid.txns[TxTypes.XMR_SWAP_B_LOCK].spend_txid.hex()
|
|
||||||
txid_hex = bid.xmr_b_lock_tx.spend_txid.hex()
|
txid_hex = bid.xmr_b_lock_tx.spend_txid.hex()
|
||||||
|
|
||||||
found_tx = ci_to.findTxnByHash(txid_hex)
|
found_tx = ci_to.findTxnByHash(txid_hex)
|
||||||
@ -2688,9 +2677,7 @@ class BasicSwap(BaseApp):
|
|||||||
bid.setState(BidStates.XMR_SWAP_SCRIPT_TX_REDEEMED) # TODO: Wait for confirmation?
|
bid.setState(BidStates.XMR_SWAP_SCRIPT_TX_REDEEMED) # TODO: Wait for confirmation?
|
||||||
|
|
||||||
if not bid.was_received:
|
if not bid.was_received:
|
||||||
#rv = True # Remove from swaps_in_progress
|
|
||||||
bid.setState(BidStates.SWAP_COMPLETED)
|
bid.setState(BidStates.SWAP_COMPLETED)
|
||||||
self.saveBidInSession(bid_id, bid, session, xmr_swap)
|
|
||||||
if bid.was_received:
|
if bid.was_received:
|
||||||
delay = random.randrange(self.min_delay_auto_accept, self.max_delay_auto_accept)
|
delay = random.randrange(self.min_delay_auto_accept, self.max_delay_auto_accept)
|
||||||
self.log.info('Redeeming coin b lock tx for bid %s in %d seconds', bid_id.hex(), delay)
|
self.log.info('Redeeming coin b lock tx for bid %s in %d seconds', bid_id.hex(), delay)
|
||||||
@ -2700,6 +2687,7 @@ class BasicSwap(BaseApp):
|
|||||||
self.log.warning('Coin a lock tx spend ignored due to bid state for bid {}'.format(bid_id.hex()))
|
self.log.warning('Coin a lock tx spend ignored due to bid state for bid {}'.format(bid_id.hex()))
|
||||||
|
|
||||||
elif spending_txid == xmr_swap.a_lock_refund_tx_id:
|
elif spending_txid == xmr_swap.a_lock_refund_tx_id:
|
||||||
|
self.log.debug('Coin a lock tx spent by lock refund tx.')
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
self.setBidError(bid.bid_id, bid, 'Unexpected txn spent coin a lock tx: {}'.format(spend_txid_hex), save_bid=False)
|
self.setBidError(bid.bid_id, bid, 'Unexpected txn spent coin a lock tx: {}'.format(spend_txid_hex), save_bid=False)
|
||||||
@ -2751,7 +2739,6 @@ class BasicSwap(BaseApp):
|
|||||||
self.log.info('Recovering xmr swap chain B lock tx for bid %s in %d seconds', bid_id.hex(), delay)
|
self.log.info('Recovering xmr swap chain B lock tx for bid %s in %d seconds', bid_id.hex(), delay)
|
||||||
self.createEventInSession(delay, EventTypes.RECOVER_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
self.createEventInSession(delay, EventTypes.RECOVER_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||||
else:
|
else:
|
||||||
#rv = True # Remove from swaps_in_progress
|
|
||||||
bid.setState(BidStates.XMR_SWAP_FAILED_REFUNDED)
|
bid.setState(BidStates.XMR_SWAP_FAILED_REFUNDED)
|
||||||
|
|
||||||
if bid.was_received:
|
if bid.was_received:
|
||||||
@ -3181,8 +3168,8 @@ class BasicSwap(BaseApp):
|
|||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
|
|
||||||
offer, xmr_offer = self.getXmrOffer(bid.offer_id, sent=True)
|
offer, xmr_offer = self.getXmrOffer(bid.offer_id, sent=True)
|
||||||
assert(offer and offer.was_sent), 'Offer not found: {}.'.format(offer_id.hex())
|
assert(offer and offer.was_sent), 'Offer not found: {}.'.format(bid.offer_id.hex())
|
||||||
assert(xmr_offer), 'XMR offer not found: {}.'.format(offer_id.hex())
|
assert(xmr_offer), 'XMR offer not found: {}.'.format(bid.offer_id.hex())
|
||||||
coin_from = Coins(offer.coin_from)
|
coin_from = Coins(offer.coin_from)
|
||||||
coin_to = Coins(offer.coin_to)
|
coin_to = Coins(offer.coin_to)
|
||||||
|
|
||||||
@ -3262,7 +3249,6 @@ class BasicSwap(BaseApp):
|
|||||||
if not ci_from.verifyPubkey(xmr_swap.pkarl):
|
if not ci_from.verifyPubkey(xmr_swap.pkarl):
|
||||||
raise ValueError('Invalid pubkey.')
|
raise ValueError('Invalid pubkey.')
|
||||||
|
|
||||||
#bid.setState(BidStates.BID_ACCEPTED)
|
|
||||||
bid.setState(BidStates.SWAP_DELAYING)
|
bid.setState(BidStates.SWAP_DELAYING)
|
||||||
self.saveBidInSession(bid.bid_id, bid, session, xmr_swap)
|
self.saveBidInSession(bid.bid_id, bid, session, xmr_swap)
|
||||||
|
|
||||||
@ -3301,8 +3287,6 @@ class BasicSwap(BaseApp):
|
|||||||
bid_id=bid_id,
|
bid_id=bid_id,
|
||||||
offer_id=offer_id,
|
offer_id=offer_id,
|
||||||
amount=bid_data.amount,
|
amount=bid_data.amount,
|
||||||
#pkhash_buyer=bid_data.pkhash_buyer,
|
|
||||||
|
|
||||||
created_at=msg['sent'],
|
created_at=msg['sent'],
|
||||||
amount_to=(bid_data.amount * offer.rate) // COIN,
|
amount_to=(bid_data.amount * offer.rate) // COIN,
|
||||||
expire_at=msg['sent'] + bid_data.time_valid,
|
expire_at=msg['sent'] + bid_data.time_valid,
|
||||||
@ -3563,17 +3547,27 @@ class BasicSwap(BaseApp):
|
|||||||
if bid.debug_ind == DebugTypes.CREATE_INVALID_COIN_B_LOCK:
|
if bid.debug_ind == DebugTypes.CREATE_INVALID_COIN_B_LOCK:
|
||||||
self.log.debug('XMR bid %s: Debug %d - Reducing lock b txn amount by 10%%.', bid_id.hex(), bid.debug_ind)
|
self.log.debug('XMR bid %s: Debug %d - Reducing lock b txn amount by 10%%.', bid_id.hex(), bid.debug_ind)
|
||||||
bid.amount_to -= int(bid.amount_to * 0.1)
|
bid.amount_to -= int(bid.amount_to * 0.1)
|
||||||
b_lock_tx_id = ci_to.publishBLockTx(xmr_swap.pkbv, xmr_swap.pkbs, bid.amount_to, xmr_offer.b_fee_rate)
|
try:
|
||||||
|
b_lock_tx_id = ci_to.publishBLockTx(xmr_swap.pkbv, xmr_swap.pkbs, bid.amount_to, xmr_offer.b_fee_rate)
|
||||||
|
except Exception as ex:
|
||||||
|
self.log.error('publishBLockTx failed for bid {} with error {}'.format(bid_id.hex(), str(ex)))
|
||||||
|
|
||||||
|
if 'not enough unlocked money' in str(ex):
|
||||||
|
delay = random.randrange(self.min_delay_auto_accept, self.max_delay_auto_accept) # TODO: New delay range
|
||||||
|
self.log.info('Retrying sending xmr swap chain B lock tx for bid %s in %d seconds', bid_id.hex(), delay)
|
||||||
|
self.createEventInSession(delay, EventTypes.SEND_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||||
|
else:
|
||||||
|
self.setBidError(bid_id, bid, 'publishBLockTx failed: ' + str(ex), save_bid=False)
|
||||||
|
self.saveBidInSession(bid_id, bid, session, xmr_swap)
|
||||||
|
return
|
||||||
|
|
||||||
self.log.debug('Submitted lock txn %s to %s chain for bid %s', b_lock_tx_id.hex(), chainparams[coin_to]['name'], bid_id.hex())
|
self.log.debug('Submitted lock txn %s to %s chain for bid %s', b_lock_tx_id.hex(), chainparams[coin_to]['name'], bid_id.hex())
|
||||||
bid.xmr_b_lock_tx = SwapTx(
|
bid.xmr_b_lock_tx = SwapTx(
|
||||||
#xmr_b_lock_tx = SwapTx(
|
|
||||||
bid_id=bid_id,
|
bid_id=bid_id,
|
||||||
tx_type=TxTypes.XMR_SWAP_B_LOCK,
|
tx_type=TxTypes.XMR_SWAP_B_LOCK,
|
||||||
txid=b_lock_tx_id,
|
txid=b_lock_tx_id,
|
||||||
)
|
)
|
||||||
bid.xmr_b_lock_tx.setState(TxStates.TX_NONE)
|
bid.xmr_b_lock_tx.setState(TxStates.TX_NONE)
|
||||||
#bid.txns[TxTypes.XMR_SWAP_B_LOCK] = xmr_b_lock_tx
|
|
||||||
|
|
||||||
self.saveBidInSession(bid_id, bid, session, xmr_swap)
|
self.saveBidInSession(bid_id, bid, session, xmr_swap)
|
||||||
|
|
||||||
@ -3688,21 +3682,14 @@ class BasicSwap(BaseApp):
|
|||||||
assert(kbsf is not None)
|
assert(kbsf is not None)
|
||||||
|
|
||||||
kbsl = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 3, for_xmr=True)
|
kbsl = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 3, for_xmr=True)
|
||||||
|
|
||||||
vkbs = ci_to.sumKeys(kbsl, kbsf)
|
vkbs = ci_to.sumKeys(kbsl, kbsf)
|
||||||
Kbs_test = ci_to.getPubkey(vkbs)
|
|
||||||
print('Kbs_test', Kbs_test.hex())
|
|
||||||
print('Kbs', xmr_swap.pkbsf.hex())
|
|
||||||
|
|
||||||
address_to = ci_to.getMainWalletAddress()
|
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)
|
||||||
|
|
||||||
bid.xmr_b_lock_tx.spend_txid = txid
|
bid.xmr_b_lock_tx.spend_txid = txid
|
||||||
#txn = bid.txns[TxTypes.XMR_SWAP_B_LOCK]
|
# TODO: Why does using bid.txns error here?
|
||||||
#print('[rm] TxTypes.XMR_SWAP_B_LOCK', txn.bid_id.hex())
|
|
||||||
#txn.spend_txid = txid
|
|
||||||
#bid.txns[TxTypes.XMR_SWAP_B_LOCK].spend_txid = txid
|
|
||||||
self.saveBidInSession(bid_id, bid, session, xmr_swap)
|
self.saveBidInSession(bid_id, bid, session, xmr_swap)
|
||||||
# Update copy of bid in swaps_in_progress
|
# Update copy of bid in swaps_in_progress
|
||||||
self.swaps_in_progress[bid_id] = (bid, offer)
|
self.swaps_in_progress[bid_id] = (bid, offer)
|
||||||
@ -3730,11 +3717,7 @@ class BasicSwap(BaseApp):
|
|||||||
assert(kbsl is not None)
|
assert(kbsl is not None)
|
||||||
|
|
||||||
kbsf = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 2, for_xmr=True)
|
kbsf = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 2, for_xmr=True)
|
||||||
|
|
||||||
vkbs = ci_to.sumKeys(kbsl, kbsf)
|
vkbs = ci_to.sumKeys(kbsl, kbsf)
|
||||||
Kbs_test = ci_to.getPubkey(vkbs)
|
|
||||||
print('Kbs_test', Kbs_test.hex())
|
|
||||||
print('Kbs', xmr_swap.pkbsf.hex())
|
|
||||||
|
|
||||||
address_to = ci_to.getMainWalletAddress()
|
address_to = ci_to.getMainWalletAddress()
|
||||||
|
|
||||||
@ -3747,7 +3730,6 @@ class BasicSwap(BaseApp):
|
|||||||
# Update copy of bid in swaps_in_progress
|
# Update copy of bid in swaps_in_progress
|
||||||
self.swaps_in_progress[bid_id] = (bid, offer)
|
self.swaps_in_progress[bid_id] = (bid, offer)
|
||||||
|
|
||||||
|
|
||||||
def processXmrBidCoinALockSigs(self, msg):
|
def processXmrBidCoinALockSigs(self, msg):
|
||||||
# Leader processing MSG3L
|
# Leader processing MSG3L
|
||||||
self.log.debug('Processing xmr coin a follower lock sigs msg %s', msg['msgid'])
|
self.log.debug('Processing xmr coin a follower lock sigs msg %s', msg['msgid'])
|
||||||
|
@ -310,4 +310,3 @@ class XmrSplitData(Base):
|
|||||||
msg_sequence = sa.Column(sa.Integer)
|
msg_sequence = sa.Column(sa.Integer)
|
||||||
dleag = sa.Column(sa.LargeBinary)
|
dleag = sa.Column(sa.LargeBinary)
|
||||||
created_at = sa.Column(sa.BigInteger)
|
created_at = sa.Column(sa.BigInteger)
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import json
|
|
||||||
import time
|
import time
|
||||||
import struct
|
import struct
|
||||||
import traceback
|
import traceback
|
||||||
@ -17,7 +16,6 @@ from jinja2 import Environment, PackageLoader
|
|||||||
|
|
||||||
from . import __version__
|
from . import __version__
|
||||||
from .util import (
|
from .util import (
|
||||||
make_int,
|
|
||||||
dumpj,
|
dumpj,
|
||||||
)
|
)
|
||||||
from .chainparams import (
|
from .chainparams import (
|
||||||
@ -26,9 +24,6 @@ from .chainparams import (
|
|||||||
)
|
)
|
||||||
from .basicswap import (
|
from .basicswap import (
|
||||||
SwapTypes,
|
SwapTypes,
|
||||||
BidStates,
|
|
||||||
TxStates,
|
|
||||||
TxTypes,
|
|
||||||
strOfferState,
|
strOfferState,
|
||||||
strBidState,
|
strBidState,
|
||||||
strTxState,
|
strTxState,
|
||||||
@ -45,6 +40,12 @@ from .js_server import (
|
|||||||
js_sentbids,
|
js_sentbids,
|
||||||
js_index,
|
js_index,
|
||||||
)
|
)
|
||||||
|
from .ui import (
|
||||||
|
PAGE_LIMIT,
|
||||||
|
inputAmount,
|
||||||
|
describeBid,
|
||||||
|
setCoinFilter,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def format_timestamp(value):
|
def format_timestamp(value):
|
||||||
@ -53,7 +54,6 @@ def format_timestamp(value):
|
|||||||
|
|
||||||
env = Environment(loader=PackageLoader('basicswap', 'templates'))
|
env = Environment(loader=PackageLoader('basicswap', 'templates'))
|
||||||
env.filters['formatts'] = format_timestamp
|
env.filters['formatts'] = format_timestamp
|
||||||
PAGE_LIMIT = 50
|
|
||||||
|
|
||||||
|
|
||||||
def getCoinName(c):
|
def getCoinName(c):
|
||||||
@ -89,141 +89,6 @@ def listExplorerActions(swap_client):
|
|||||||
return actions
|
return actions
|
||||||
|
|
||||||
|
|
||||||
def listBidStates():
|
|
||||||
rv = []
|
|
||||||
for s in BidStates:
|
|
||||||
rv.append((int(s), strBidState(s)))
|
|
||||||
return rv
|
|
||||||
|
|
||||||
|
|
||||||
def getTxIdHex(bid, tx_type, prefix):
|
|
||||||
if tx_type == TxTypes.ITX:
|
|
||||||
obj = bid.initiate_tx
|
|
||||||
elif tx_type == TxTypes.PTX:
|
|
||||||
obj = bid.participate_tx
|
|
||||||
else:
|
|
||||||
return 'Unknown Type'
|
|
||||||
|
|
||||||
if not obj:
|
|
||||||
return 'None'
|
|
||||||
if not obj.txid:
|
|
||||||
return 'None'
|
|
||||||
return obj.txid.hex() + prefix
|
|
||||||
|
|
||||||
|
|
||||||
def getTxSpendHex(bid, tx_type):
|
|
||||||
if tx_type == TxTypes.ITX:
|
|
||||||
obj = bid.initiate_tx
|
|
||||||
elif tx_type == TxTypes.PTX:
|
|
||||||
obj = bid.participate_tx
|
|
||||||
else:
|
|
||||||
return 'Unknown Type'
|
|
||||||
|
|
||||||
if not obj:
|
|
||||||
return 'None'
|
|
||||||
if not obj.spend_txid:
|
|
||||||
return 'None'
|
|
||||||
return obj.spend_txid.hex() + ' {}'.format(obj.spend_n)
|
|
||||||
|
|
||||||
|
|
||||||
def validateAmountString(amount):
|
|
||||||
if type(amount) != str:
|
|
||||||
return
|
|
||||||
ar = amount.split('.')
|
|
||||||
if len(ar) > 1 and len(ar[1]) > 8:
|
|
||||||
raise ValueError('Too many decimal places in amount {}'.format(amount))
|
|
||||||
|
|
||||||
|
|
||||||
def inputAmount(amount_str):
|
|
||||||
validateAmountString(amount_str)
|
|
||||||
return make_int(amount_str)
|
|
||||||
|
|
||||||
|
|
||||||
def setCoinFilter(form_data, field_name):
|
|
||||||
if field_name not in form_data:
|
|
||||||
return -1
|
|
||||||
coin_type = int(form_data[field_name][0])
|
|
||||||
if coin_type == -1:
|
|
||||||
return -1
|
|
||||||
try:
|
|
||||||
return Coins(coin_type)
|
|
||||||
except Exception:
|
|
||||||
raise ValueError('Unknown Coin Type {}'.format(str(field_name)))
|
|
||||||
|
|
||||||
|
|
||||||
def describeBid(swap_client, bid, offer, edit_bid, show_txns):
|
|
||||||
|
|
||||||
coin_from = Coins(offer.coin_from)
|
|
||||||
coin_to = Coins(offer.coin_to)
|
|
||||||
ci_from = swap_client.ci(coin_from)
|
|
||||||
ci_to = swap_client.ci(coin_to)
|
|
||||||
ticker_from = swap_client.getTicker(coin_from)
|
|
||||||
ticker_to = swap_client.getTicker(coin_to)
|
|
||||||
|
|
||||||
if bid.state == BidStates.BID_SENT:
|
|
||||||
state_description = 'Waiting for seller to accept.'
|
|
||||||
elif bid.state == BidStates.BID_RECEIVED:
|
|
||||||
state_description = 'Waiting for seller to accept.'
|
|
||||||
elif bid.state == BidStates.BID_ACCEPTED:
|
|
||||||
if not bid.initiate_tx:
|
|
||||||
state_description = 'Waiting for seller to send initiate tx.'
|
|
||||||
else:
|
|
||||||
state_description = 'Waiting for initiate tx to confirm.'
|
|
||||||
elif bid.state == BidStates.SWAP_INITIATED:
|
|
||||||
state_description = 'Waiting for participate txn to be confirmed in {} chain'.format(ticker_to)
|
|
||||||
elif bid.state == BidStates.SWAP_PARTICIPATING:
|
|
||||||
state_description = 'Waiting for initiate txn to be spent in {} chain'.format(ticker_from)
|
|
||||||
elif bid.state == BidStates.SWAP_COMPLETED:
|
|
||||||
state_description = 'Swap completed'
|
|
||||||
if bid.getITxState() == TxStates.TX_REDEEMED and bid.getPTxState() == TxStates.TX_REDEEMED:
|
|
||||||
state_description += ' successfully'
|
|
||||||
else:
|
|
||||||
state_description += ', ITX ' + strTxState(bid.getITxState()) + ', PTX ' + strTxState(bid.getPTxState())
|
|
||||||
elif bid.state == BidStates.SWAP_TIMEDOUT:
|
|
||||||
state_description = 'Timed out waiting for initiate txn'
|
|
||||||
elif bid.state == BidStates.BID_ABANDONED:
|
|
||||||
state_description = 'Bid abandoned'
|
|
||||||
elif bid.state == BidStates.BID_ERROR:
|
|
||||||
state_description = bid.state_note
|
|
||||||
else:
|
|
||||||
state_description = ''
|
|
||||||
|
|
||||||
data = {
|
|
||||||
'amt_from': ci_from.format_amount(bid.amount),
|
|
||||||
'amt_to': ci_to.format_amount((bid.amount * offer.rate) // ci_from.COIN()),
|
|
||||||
'ticker_from': ticker_from,
|
|
||||||
'ticker_to': ticker_to,
|
|
||||||
'bid_state': strBidState(bid.state),
|
|
||||||
'state_description': state_description,
|
|
||||||
'itx_state': strTxState(bid.getITxState()),
|
|
||||||
'ptx_state': strTxState(bid.getPTxState()),
|
|
||||||
'offer_id': bid.offer_id.hex(),
|
|
||||||
'addr_from': bid.bid_addr,
|
|
||||||
'addr_fund_proof': bid.proof_address,
|
|
||||||
'created_at': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(bid.created_at)),
|
|
||||||
'expired_at': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(bid.expire_at)),
|
|
||||||
'was_sent': 'True' if bid.was_sent else 'False',
|
|
||||||
'was_received': 'True' if bid.was_received else 'False',
|
|
||||||
'initiate_tx': getTxIdHex(bid, TxTypes.ITX, ' ' + ticker_from),
|
|
||||||
'initiate_conf': 'None' if (not bid.initiate_tx or not bid.initiate_tx.conf) else bid.initiate_tx.conf,
|
|
||||||
'participate_tx': getTxIdHex(bid, TxTypes.PTX, ' ' + ticker_to),
|
|
||||||
'participate_conf': 'None' if (not bid.participate_tx or not bid.participate_tx.conf) else bid.participate_tx.conf,
|
|
||||||
'show_txns': show_txns,
|
|
||||||
}
|
|
||||||
|
|
||||||
if edit_bid:
|
|
||||||
data['bid_state_ind'] = int(bid.state)
|
|
||||||
data['bid_states'] = listBidStates()
|
|
||||||
|
|
||||||
if show_txns:
|
|
||||||
data['initiate_tx_refund'] = 'None' if not bid.initiate_txn_refund else bid.initiate_txn_refund.hex()
|
|
||||||
data['participate_tx_refund'] = 'None' if not bid.participate_txn_refund else bid.participate_txn_refund.hex()
|
|
||||||
data['initiate_tx_spend'] = getTxSpendHex(bid, TxTypes.ITX)
|
|
||||||
data['participate_tx_spend'] = getTxSpendHex(bid, TxTypes.PTX)
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
def html_content_start(title, h2=None, refresh=None):
|
def html_content_start(title, h2=None, refresh=None):
|
||||||
content = '<!DOCTYPE html><html lang="en">\n<head>' \
|
content = '<!DOCTYPE html><html lang="en">\n<head>' \
|
||||||
+ '<meta charset="UTF-8">' \
|
+ '<meta charset="UTF-8">' \
|
||||||
|
@ -362,7 +362,6 @@ class BTCInterface(CoinInterface):
|
|||||||
tx.nVersion = self.txVersion()
|
tx.nVersion = self.txVersion()
|
||||||
tx.vin.append(CTxIn(COutPoint(tx_lock_refund_hash_int, locked_n), nSequence=0))
|
tx.vin.append(CTxIn(COutPoint(tx_lock_refund_hash_int, locked_n), nSequence=0))
|
||||||
|
|
||||||
#pubkeyhash = hash160(Kal)
|
|
||||||
tx.vout.append(self.txoType(locked_coin, CScript([OP_0, pkh_refund_to])))
|
tx.vout.append(self.txoType(locked_coin, CScript([OP_0, pkh_refund_to])))
|
||||||
|
|
||||||
witness_bytes = len(script_lock_refund)
|
witness_bytes = len(script_lock_refund)
|
||||||
@ -591,9 +590,11 @@ class BTCInterface(CoinInterface):
|
|||||||
assert_cond(len(tx.vout) == 1, 'tx doesn\'t have one output')
|
assert_cond(len(tx.vout) == 1, 'tx doesn\'t have one output')
|
||||||
|
|
||||||
# Destination doesn't matter to the follower
|
# Destination doesn't matter to the follower
|
||||||
#p2wpkh = CScript([OP_0, hash160(Kal)])
|
'''
|
||||||
#locked_n = findOutput(tx, p2wpkh)
|
p2wpkh = CScript([OP_0, hash160(Kal)])
|
||||||
#assert_cond(locked_n is not None, 'Output not found in lock refund spend tx')
|
locked_n = findOutput(tx, p2wpkh)
|
||||||
|
assert_cond(locked_n is not None, 'Output not found in lock refund spend tx')
|
||||||
|
'''
|
||||||
tx_value = tx.vout[0].nValue
|
tx_value = tx.vout[0].nValue
|
||||||
|
|
||||||
fee_paid = prevout_value - tx_value
|
fee_paid = prevout_value - tx_value
|
||||||
@ -711,8 +712,6 @@ class BTCInterface(CoinInterface):
|
|||||||
|
|
||||||
def signTxWithWallet(self, tx):
|
def signTxWithWallet(self, tx):
|
||||||
rv = self.rpc_callback('signrawtransactionwithwallet', [tx.hex()])
|
rv = self.rpc_callback('signrawtransactionwithwallet', [tx.hex()])
|
||||||
|
|
||||||
#return FromHex(tx, rv['hex'])
|
|
||||||
return bytes.fromhex(rv['hex'])
|
return bytes.fromhex(rv['hex'])
|
||||||
|
|
||||||
def publishTx(self, tx):
|
def publishTx(self, tx):
|
||||||
@ -798,7 +797,6 @@ class BTCInterface(CoinInterface):
|
|||||||
|
|
||||||
def recoverEncKey(self, esig, sig, K):
|
def recoverEncKey(self, esig, sig, K):
|
||||||
return ecdsaotves_rec_enc_key(K, esig, sig[:-1]) # Strip sighash type
|
return ecdsaotves_rec_enc_key(K, esig, sig[:-1]) # Strip sighash type
|
||||||
#return otves.RecoverEncKey(esig, sig[:-1], K) # Strip sighash type
|
|
||||||
|
|
||||||
def getTxVSize(self, tx, add_bytes=0, add_witness_bytes=0):
|
def getTxVSize(self, tx, add_bytes=0, add_witness_bytes=0):
|
||||||
wsf = self.witnessScaleFactor()
|
wsf = self.witnessScaleFactor()
|
||||||
@ -845,12 +843,6 @@ class BTCInterface(CoinInterface):
|
|||||||
def getOutput(self, txid, dest_script, expect_value):
|
def getOutput(self, txid, dest_script, expect_value):
|
||||||
# TODO: Use getrawtransaction if txindex is active
|
# TODO: Use getrawtransaction if txindex is active
|
||||||
utxos = self.rpc_callback('scantxoutset', ['start', ['raw({})'.format(dest_script.hex())]])
|
utxos = self.rpc_callback('scantxoutset', ['start', ['raw({})'.format(dest_script.hex())]])
|
||||||
'''
|
|
||||||
bech32_prefix = chainparams[self.coin_type()][self._network]['hrp']
|
|
||||||
address = segwit_addr.encode(bech32_prefix, 0, list(dest_script[2:]))
|
|
||||||
print('[rm] address', address)
|
|
||||||
utxos = self.rpc_callback('scantxoutset', ['start', ['addr({})'.format(address)]])
|
|
||||||
'''
|
|
||||||
chain_height = utxos['height']
|
chain_height = utxos['height']
|
||||||
rv = []
|
rv = []
|
||||||
for utxo in utxos['unspents']:
|
for utxo in utxos['unspents']:
|
||||||
@ -871,7 +863,6 @@ class BTCInterface(CoinInterface):
|
|||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def testBTCInterface():
|
def testBTCInterface():
|
||||||
print('testBTCInterface')
|
print('testBTCInterface')
|
||||||
script_bytes = bytes.fromhex('6382012088a820aaf125ff9a34a74c7a17f5e7ee9d07d17cc5e53a539f345d5f73baa7e79b65e28852210224019219ad43c47288c937ae508f26998dd81ec066827773db128fd5e262c04f21039a0fd752bd1a2234820707852e7a30253620052ecd162948a06532a817710b5952ae670114b2755221038689deba25c5578e5457ddadbaf8aeb8badf438dc22f540503dbd4ae10e14f512103c9c5d5acc996216d10852a72cd67c701bfd4b9137a4076350fd32f08db39575552ae68')
|
script_bytes = bytes.fromhex('6382012088a820aaf125ff9a34a74c7a17f5e7ee9d07d17cc5e53a539f345d5f73baa7e79b65e28852210224019219ad43c47288c937ae508f26998dd81ec066827773db128fd5e262c04f21039a0fd752bd1a2234820707852e7a30253620052ecd162948a06532a817710b5952ae670114b2755221038689deba25c5578e5457ddadbaf8aeb8badf438dc22f540503dbd4ae10e14f512103c9c5d5acc996216d10852a72cd67c701bfd4b9137a4076350fd32f08db39575552ae68')
|
||||||
@ -954,6 +945,5 @@ def testBTCInterface():
|
|||||||
print('Passed.')
|
print('Passed.')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
testBTCInterface()
|
testBTCInterface()
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
from .interface_btc import BTCInterface
|
from .interface_btc import BTCInterface
|
||||||
from .chainparams import Coins
|
from .chainparams import Coins
|
||||||
|
|
||||||
|
|
||||||
class LTCInterface(BTCInterface):
|
class LTCInterface(BTCInterface):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def coin_type():
|
def coin_type():
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
from .interface_btc import BTCInterface
|
from .interface_btc import BTCInterface
|
||||||
from .chainparams import Coins
|
from .chainparams import Coins
|
||||||
|
|
||||||
|
|
||||||
class NMCInterface(BTCInterface):
|
class NMCInterface(BTCInterface):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def coin_type():
|
def coin_type():
|
||||||
|
@ -151,6 +151,7 @@ class XMRInterface(CoinInterface):
|
|||||||
return self.encodePubkey(edf.edwards_add(Ka_d, Kb_d))
|
return self.encodePubkey(edf.edwards_add(Ka_d, Kb_d))
|
||||||
|
|
||||||
def publishBLockTx(self, Kbv, Kbs, output_amount, feerate):
|
def publishBLockTx(self, Kbv, Kbs, output_amount, feerate):
|
||||||
|
self.rpc_wallet_cb('open_wallet', {'filename': self._wallet_filename})
|
||||||
|
|
||||||
shared_addr = xmr_util.encode_address(Kbv, Kbs)
|
shared_addr = xmr_util.encode_address(Kbv, Kbs)
|
||||||
|
|
||||||
@ -158,11 +159,18 @@ class XMRInterface(CoinInterface):
|
|||||||
params = {'destinations': [{'amount': output_amount, 'address': shared_addr}]}
|
params = {'destinations': [{'amount': output_amount, 'address': shared_addr}]}
|
||||||
rv = self.rpc_wallet_cb('transfer', params)
|
rv = self.rpc_wallet_cb('transfer', params)
|
||||||
logging.info('publishBLockTx %s to address_b58 %s', rv['tx_hash'], shared_addr)
|
logging.info('publishBLockTx %s to address_b58 %s', rv['tx_hash'], shared_addr)
|
||||||
|
tx_hash = bytes.fromhex(rv['tx_hash'])
|
||||||
|
|
||||||
return bytes.fromhex(rv['tx_hash'])
|
# Debug
|
||||||
|
for i in range(10):
|
||||||
|
params = {'out': True, 'pending': True, 'failed': True, 'pool': True, }
|
||||||
|
rv = self.rpc_wallet_cb('get_transfers', params)
|
||||||
|
logging.info('[rm] get_transfers {}'.format(dumpj(rv)))
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
return tx_hash
|
||||||
|
|
||||||
def findTxB(self, kbv, Kbs, cb_swap_value, cb_block_confirmed, restore_height):
|
def findTxB(self, kbv, Kbs, cb_swap_value, cb_block_confirmed, restore_height):
|
||||||
#Kbv_enc = self.encodePubkey(self.pubkey(kbv))
|
|
||||||
Kbv = self.getPubkey(kbv)
|
Kbv = self.getPubkey(kbv)
|
||||||
address_b58 = xmr_util.encode_address(Kbv, Kbs)
|
address_b58 = xmr_util.encode_address(Kbv, Kbs)
|
||||||
|
|
||||||
@ -176,7 +184,6 @@ class XMRInterface(CoinInterface):
|
|||||||
'restore_height': restore_height,
|
'restore_height': restore_height,
|
||||||
'filename': address_b58,
|
'filename': address_b58,
|
||||||
'address': address_b58,
|
'address': address_b58,
|
||||||
#'viewkey': b2h(intToBytes32_le(kbv)),
|
|
||||||
'viewkey': b2h(kbv_le),
|
'viewkey': b2h(kbv_le),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +227,7 @@ class XMRInterface(CoinInterface):
|
|||||||
params = {
|
params = {
|
||||||
'filename': address_b58,
|
'filename': address_b58,
|
||||||
'address': address_b58,
|
'address': address_b58,
|
||||||
'viewkey': b2h(intToBytes32_le(kbv)),
|
'viewkey': b2h(kbv[::-1]),
|
||||||
'restore_height': restore_height,
|
'restore_height': restore_height,
|
||||||
}
|
}
|
||||||
self.rpc_wallet_cb('generate_from_keys', params)
|
self.rpc_wallet_cb('generate_from_keys', params)
|
||||||
|
@ -4,45 +4,31 @@
|
|||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
import struct
|
|
||||||
import traceback
|
|
||||||
import threading
|
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from . import __version__
|
from .util import format8
|
||||||
from .util import (
|
|
||||||
COIN,
|
|
||||||
format8,
|
|
||||||
make_int,
|
|
||||||
dumpj,
|
|
||||||
)
|
|
||||||
from .chainparams import (
|
|
||||||
chainparams,
|
|
||||||
Coins,
|
|
||||||
)
|
|
||||||
from .basicswap import (
|
from .basicswap import (
|
||||||
SwapTypes,
|
|
||||||
BidStates,
|
|
||||||
TxStates,
|
|
||||||
TxTypes,
|
|
||||||
strOfferState,
|
|
||||||
strBidState,
|
strBidState,
|
||||||
strTxState,
|
|
||||||
getLockName,
|
|
||||||
SEQUENCE_LOCK_TIME,
|
|
||||||
ABS_LOCK_TIME,
|
|
||||||
)
|
)
|
||||||
|
from .ui import (
|
||||||
|
PAGE_LIMIT,
|
||||||
|
inputAmount,
|
||||||
|
describeBid,
|
||||||
|
setCoinFilter,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def js_error(self, error_str):
|
def js_error(self, error_str):
|
||||||
error_str_json = json.dumps({'error': error_str})
|
error_str_json = json.dumps({'error': error_str})
|
||||||
return bytes(error_str_json, 'UTF-8')
|
return bytes(error_str_json, 'UTF-8')
|
||||||
|
|
||||||
|
|
||||||
def js_wallets(self, url_split, post_string):
|
def js_wallets(self, url_split, post_string):
|
||||||
return bytes(json.dumps(self.server.swap_client.getWalletsInfo()), 'UTF-8')
|
return bytes(json.dumps(self.server.swap_client.getWalletsInfo()), 'UTF-8')
|
||||||
|
|
||||||
|
|
||||||
def js_offers(self, url_split, post_string, sent=False):
|
def js_offers(self, url_split, post_string, sent=False):
|
||||||
if len(url_split) > 3:
|
if len(url_split) > 3:
|
||||||
if url_split[3] == 'new':
|
if url_split[3] == 'new':
|
||||||
@ -82,27 +68,28 @@ def js_offers(self, url_split, post_string, sent=False):
|
|||||||
filters['limit'] = int(post_data[b'limit'][0])
|
filters['limit'] = int(post_data[b'limit'][0])
|
||||||
assert(filters['limit'] > 0 and filters['limit'] <= PAGE_LIMIT), 'Invalid limit'
|
assert(filters['limit'] > 0 and filters['limit'] <= PAGE_LIMIT), 'Invalid limit'
|
||||||
|
|
||||||
ci_from = self.server.swap_client.ci(o.coin_from)
|
|
||||||
ci_to = self.server.swap_client.ci(o.coin_to)
|
|
||||||
|
|
||||||
offers = self.server.swap_client.listOffers(sent, filters)
|
offers = self.server.swap_client.listOffers(sent, filters)
|
||||||
rv = []
|
rv = []
|
||||||
for o in offers:
|
for o in offers:
|
||||||
|
ci_from = self.server.swap_client.ci(o.coin_from)
|
||||||
|
ci_to = self.server.swap_client.ci(o.coin_to)
|
||||||
rv.append({
|
rv.append({
|
||||||
'offer_id': o.offer_id.hex(),
|
'offer_id': o.offer_id.hex(),
|
||||||
'created_at': time.strftime('%Y-%m-%d %H:%M', time.localtime(o.created_at)),
|
'created_at': time.strftime('%Y-%m-%d %H:%M', time.localtime(o.created_at)),
|
||||||
'coin_from': ci_from.coin_name(),
|
'coin_from': ci_from.coin_name(),
|
||||||
'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) // COIN),
|
'amount_to': ci_to.format_amount((o.amount_from * o.rate) // ci_from.COIN()),
|
||||||
'rate': format8(o.rate)
|
'rate': ci_to.format_amount(o.rate)
|
||||||
})
|
})
|
||||||
|
|
||||||
return bytes(json.dumps(rv), 'UTF-8')
|
return bytes(json.dumps(rv), 'UTF-8')
|
||||||
|
|
||||||
|
|
||||||
def js_sentoffers(self, url_split, post_string):
|
def js_sentoffers(self, url_split, post_string):
|
||||||
return self.js_offers(url_split, post_string, True)
|
return self.js_offers(url_split, post_string, True)
|
||||||
|
|
||||||
|
|
||||||
def js_bids(self, url_split, post_string):
|
def js_bids(self, url_split, post_string):
|
||||||
swap_client = self.server.swap_client
|
swap_client = self.server.swap_client
|
||||||
if len(url_split) > 3:
|
if len(url_split) > 3:
|
||||||
@ -153,8 +140,10 @@ def js_bids(self, url_split, post_string):
|
|||||||
'bid_state': strBidState(b[4])
|
'bid_state': strBidState(b[4])
|
||||||
} for b in bids]), 'UTF-8')
|
} for b in bids]), 'UTF-8')
|
||||||
|
|
||||||
|
|
||||||
def js_sentbids(self, url_split, post_string):
|
def js_sentbids(self, url_split, post_string):
|
||||||
return bytes(json.dumps(self.server.swap_client.listBids(sent=True)), 'UTF-8')
|
return bytes(json.dumps(self.server.swap_client.listBids(sent=True)), 'UTF-8')
|
||||||
|
|
||||||
|
|
||||||
def js_index(self, url_split, post_string):
|
def js_index(self, url_split, post_string):
|
||||||
return bytes(json.dumps(self.server.swap_client.getSummary()), 'UTF-8')
|
return bytes(json.dumps(self.server.swap_client.getSummary()), 'UTF-8')
|
||||||
|
13
basicswap/network.py
Normal file
13
basicswap/network.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2020 tecnovert
|
||||||
|
# Distributed under the MIT software license, see the accompanying
|
||||||
|
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
'''
|
||||||
|
TODO:
|
||||||
|
'''
|
||||||
|
|
||||||
|
class Peer:
|
||||||
|
pass
|
158
basicswap/ui.py
Normal file
158
basicswap/ui.py
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2020 tecnovert
|
||||||
|
# Distributed under the MIT software license, see the accompanying
|
||||||
|
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from .util import (
|
||||||
|
make_int,
|
||||||
|
)
|
||||||
|
from .chainparams import (
|
||||||
|
Coins,
|
||||||
|
)
|
||||||
|
from .basicswap import (
|
||||||
|
BidStates,
|
||||||
|
TxStates,
|
||||||
|
TxTypes,
|
||||||
|
strBidState,
|
||||||
|
strTxState,
|
||||||
|
)
|
||||||
|
|
||||||
|
PAGE_LIMIT = 50
|
||||||
|
|
||||||
|
|
||||||
|
def validateAmountString(amount):
|
||||||
|
if type(amount) != str:
|
||||||
|
return
|
||||||
|
ar = amount.split('.')
|
||||||
|
if len(ar) > 1 and len(ar[1]) > 8:
|
||||||
|
raise ValueError('Too many decimal places in amount {}'.format(amount))
|
||||||
|
|
||||||
|
|
||||||
|
def inputAmount(amount_str):
|
||||||
|
validateAmountString(amount_str)
|
||||||
|
return make_int(amount_str)
|
||||||
|
|
||||||
|
|
||||||
|
def setCoinFilter(form_data, field_name):
|
||||||
|
if field_name not in form_data:
|
||||||
|
return -1
|
||||||
|
coin_type = int(form_data[field_name][0])
|
||||||
|
if coin_type == -1:
|
||||||
|
return -1
|
||||||
|
try:
|
||||||
|
return Coins(coin_type)
|
||||||
|
except Exception:
|
||||||
|
raise ValueError('Unknown Coin Type {}'.format(str(field_name)))
|
||||||
|
|
||||||
|
|
||||||
|
def getTxIdHex(bid, tx_type, prefix):
|
||||||
|
if tx_type == TxTypes.ITX:
|
||||||
|
obj = bid.initiate_tx
|
||||||
|
elif tx_type == TxTypes.PTX:
|
||||||
|
obj = bid.participate_tx
|
||||||
|
else:
|
||||||
|
return 'Unknown Type'
|
||||||
|
|
||||||
|
if not obj:
|
||||||
|
return 'None'
|
||||||
|
if not obj.txid:
|
||||||
|
return 'None'
|
||||||
|
return obj.txid.hex() + prefix
|
||||||
|
|
||||||
|
|
||||||
|
def getTxSpendHex(bid, tx_type):
|
||||||
|
if tx_type == TxTypes.ITX:
|
||||||
|
obj = bid.initiate_tx
|
||||||
|
elif tx_type == TxTypes.PTX:
|
||||||
|
obj = bid.participate_tx
|
||||||
|
else:
|
||||||
|
return 'Unknown Type'
|
||||||
|
|
||||||
|
if not obj:
|
||||||
|
return 'None'
|
||||||
|
if not obj.spend_txid:
|
||||||
|
return 'None'
|
||||||
|
return obj.spend_txid.hex() + ' {}'.format(obj.spend_n)
|
||||||
|
|
||||||
|
|
||||||
|
def listBidStates():
|
||||||
|
rv = []
|
||||||
|
for s in BidStates:
|
||||||
|
rv.append((int(s), strBidState(s)))
|
||||||
|
return rv
|
||||||
|
|
||||||
|
|
||||||
|
def describeBid(swap_client, bid, offer, edit_bid, show_txns):
|
||||||
|
|
||||||
|
coin_from = Coins(offer.coin_from)
|
||||||
|
coin_to = Coins(offer.coin_to)
|
||||||
|
ci_from = swap_client.ci(coin_from)
|
||||||
|
ci_to = swap_client.ci(coin_to)
|
||||||
|
ticker_from = swap_client.getTicker(coin_from)
|
||||||
|
ticker_to = swap_client.getTicker(coin_to)
|
||||||
|
|
||||||
|
if bid.state == BidStates.BID_SENT:
|
||||||
|
state_description = 'Waiting for seller to accept.'
|
||||||
|
elif bid.state == BidStates.BID_RECEIVED:
|
||||||
|
state_description = 'Waiting for seller to accept.'
|
||||||
|
elif bid.state == BidStates.BID_ACCEPTED:
|
||||||
|
if not bid.initiate_tx:
|
||||||
|
state_description = 'Waiting for seller to send initiate tx.'
|
||||||
|
else:
|
||||||
|
state_description = 'Waiting for initiate tx to confirm.'
|
||||||
|
elif bid.state == BidStates.SWAP_INITIATED:
|
||||||
|
state_description = 'Waiting for participate txn to be confirmed in {} chain'.format(ticker_to)
|
||||||
|
elif bid.state == BidStates.SWAP_PARTICIPATING:
|
||||||
|
state_description = 'Waiting for initiate txn to be spent in {} chain'.format(ticker_from)
|
||||||
|
elif bid.state == BidStates.SWAP_COMPLETED:
|
||||||
|
state_description = 'Swap completed'
|
||||||
|
if bid.getITxState() == TxStates.TX_REDEEMED and bid.getPTxState() == TxStates.TX_REDEEMED:
|
||||||
|
state_description += ' successfully'
|
||||||
|
else:
|
||||||
|
state_description += ', ITX ' + strTxState(bid.getITxState()) + ', PTX ' + strTxState(bid.getPTxState())
|
||||||
|
elif bid.state == BidStates.SWAP_TIMEDOUT:
|
||||||
|
state_description = 'Timed out waiting for initiate txn'
|
||||||
|
elif bid.state == BidStates.BID_ABANDONED:
|
||||||
|
state_description = 'Bid abandoned'
|
||||||
|
elif bid.state == BidStates.BID_ERROR:
|
||||||
|
state_description = bid.state_note
|
||||||
|
else:
|
||||||
|
state_description = ''
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'amt_from': ci_from.format_amount(bid.amount),
|
||||||
|
'amt_to': ci_to.format_amount((bid.amount * offer.rate) // ci_from.COIN()),
|
||||||
|
'ticker_from': ticker_from,
|
||||||
|
'ticker_to': ticker_to,
|
||||||
|
'bid_state': strBidState(bid.state),
|
||||||
|
'state_description': state_description,
|
||||||
|
'itx_state': strTxState(bid.getITxState()),
|
||||||
|
'ptx_state': strTxState(bid.getPTxState()),
|
||||||
|
'offer_id': bid.offer_id.hex(),
|
||||||
|
'addr_from': bid.bid_addr,
|
||||||
|
'addr_fund_proof': bid.proof_address,
|
||||||
|
'created_at': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(bid.created_at)),
|
||||||
|
'expired_at': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(bid.expire_at)),
|
||||||
|
'was_sent': 'True' if bid.was_sent else 'False',
|
||||||
|
'was_received': 'True' if bid.was_received else 'False',
|
||||||
|
'initiate_tx': getTxIdHex(bid, TxTypes.ITX, ' ' + ticker_from),
|
||||||
|
'initiate_conf': 'None' if (not bid.initiate_tx or not bid.initiate_tx.conf) else bid.initiate_tx.conf,
|
||||||
|
'participate_tx': getTxIdHex(bid, TxTypes.PTX, ' ' + ticker_to),
|
||||||
|
'participate_conf': 'None' if (not bid.participate_tx or not bid.participate_tx.conf) else bid.participate_tx.conf,
|
||||||
|
'show_txns': show_txns,
|
||||||
|
}
|
||||||
|
|
||||||
|
if edit_bid:
|
||||||
|
data['bid_state_ind'] = int(bid.state)
|
||||||
|
data['bid_states'] = listBidStates()
|
||||||
|
|
||||||
|
if show_txns:
|
||||||
|
data['initiate_tx_refund'] = 'None' if not bid.initiate_txn_refund else bid.initiate_txn_refund.hex()
|
||||||
|
data['participate_tx_refund'] = 'None' if not bid.participate_txn_refund else bid.participate_txn_refund.hex()
|
||||||
|
data['initiate_tx_spend'] = getTxSpendHex(bid, TxTypes.ITX)
|
||||||
|
data['participate_tx_spend'] = getTxSpendHex(bid, TxTypes.PTX)
|
||||||
|
|
||||||
|
return data
|
@ -27,7 +27,6 @@ from basicswap.util import (
|
|||||||
SerialiseNum,
|
SerialiseNum,
|
||||||
DeserialiseNum,
|
DeserialiseNum,
|
||||||
make_int,
|
make_int,
|
||||||
format8,
|
|
||||||
format_amount,
|
format_amount,
|
||||||
validate_amount,
|
validate_amount,
|
||||||
)
|
)
|
||||||
@ -39,9 +38,6 @@ from basicswap.basicswap import (
|
|||||||
SEQUENCE_LOCK_TIME,
|
SEQUENCE_LOCK_TIME,
|
||||||
)
|
)
|
||||||
|
|
||||||
from basicswap.ecc_util import (
|
|
||||||
i2b)
|
|
||||||
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
def test_serialise_num(self):
|
def test_serialise_num(self):
|
||||||
@ -214,6 +210,5 @@ class Test(unittest.TestCase):
|
|||||||
assert('12.00000000' == format_amount(amount_to, scale_to))
|
assert('12.00000000' == format_amount(amount_to, scale_to))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -23,14 +23,12 @@ from basicswap.basicswap import (
|
|||||||
Coins,
|
Coins,
|
||||||
SwapTypes,
|
SwapTypes,
|
||||||
BidStates,
|
BidStates,
|
||||||
TxStates,
|
|
||||||
DebugTypes,
|
DebugTypes,
|
||||||
SEQUENCE_LOCK_BLOCKS,
|
SEQUENCE_LOCK_BLOCKS,
|
||||||
)
|
)
|
||||||
from basicswap.util import (
|
from basicswap.util import (
|
||||||
COIN,
|
COIN,
|
||||||
toWIF,
|
toWIF,
|
||||||
dumpje,
|
|
||||||
make_int,
|
make_int,
|
||||||
)
|
)
|
||||||
from basicswap.rpc import (
|
from basicswap.rpc import (
|
||||||
@ -340,7 +338,6 @@ class Test(unittest.TestCase):
|
|||||||
logger.propagate = False
|
logger.propagate = False
|
||||||
logger.handlers = []
|
logger.handlers = []
|
||||||
logger.setLevel(logging.INFO) # DEBUG shows many messages from requests.post
|
logger.setLevel(logging.INFO) # DEBUG shows many messages from requests.post
|
||||||
#logger.setLevel(logging.DEBUG)
|
|
||||||
formatter = logging.Formatter('%(asctime)s %(levelname)s : %(message)s')
|
formatter = logging.Formatter('%(asctime)s %(levelname)s : %(message)s')
|
||||||
stream_stdout = logging.StreamHandler()
|
stream_stdout = logging.StreamHandler()
|
||||||
stream_stdout.setFormatter(formatter)
|
stream_stdout.setFormatter(formatter)
|
||||||
@ -573,15 +570,14 @@ 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)
|
||||||
|
|
||||||
self.delay_for(600) # [rm]
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
js_w0_before = json.loads(urlopen('http://localhost:1800/json/wallets').read())
|
js_w0_before = json.loads(urlopen('http://localhost:1800/json/wallets').read())
|
||||||
|
|
||||||
offer_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, 101 * COIN, 0.12 * XMR_COIN, 101 * COIN, SwapTypes.XMR_SWAP,
|
offer_id = swap_clients[0].postOffer(
|
||||||
|
Coins.PART, Coins.XMR, 101 * COIN, 0.12 * XMR_COIN, 101 * COIN, SwapTypes.XMR_SWAP,
|
||||||
lock_type=SEQUENCE_LOCK_BLOCKS, lock_value=12)
|
lock_type=SEQUENCE_LOCK_BLOCKS, lock_value=12)
|
||||||
self.wait_for_offer(swap_clients[1], offer_id)
|
self.wait_for_offer(swap_clients[1], offer_id)
|
||||||
offer = swap_clients[1].getOffer(offer_id)
|
offer = swap_clients[1].getOffer(offer_id)
|
||||||
@ -610,7 +606,8 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
js_w0_before = json.loads(urlopen('http://localhost:1800/json/wallets').read())
|
js_w0_before = json.loads(urlopen('http://localhost:1800/json/wallets').read())
|
||||||
|
|
||||||
offer_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, 101 * COIN, 0.13 * XMR_COIN, 101 * COIN, SwapTypes.XMR_SWAP,
|
offer_id = swap_clients[0].postOffer(
|
||||||
|
Coins.PART, Coins.XMR, 101 * COIN, 0.13 * XMR_COIN, 101 * COIN, SwapTypes.XMR_SWAP,
|
||||||
lock_type=SEQUENCE_LOCK_BLOCKS, lock_value=12)
|
lock_type=SEQUENCE_LOCK_BLOCKS, lock_value=12)
|
||||||
self.wait_for_offer(swap_clients[1], offer_id)
|
self.wait_for_offer(swap_clients[1], offer_id)
|
||||||
offer = swap_clients[1].getOffer(offer_id)
|
offer = swap_clients[1].getOffer(offer_id)
|
||||||
@ -637,7 +634,8 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
swap_clients = self.swap_clients
|
swap_clients = self.swap_clients
|
||||||
|
|
||||||
offer_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, 101 * COIN, 0.14 * XMR_COIN, 101 * COIN, SwapTypes.XMR_SWAP,
|
offer_id = swap_clients[0].postOffer(
|
||||||
|
Coins.PART, Coins.XMR, 101 * COIN, 0.14 * XMR_COIN, 101 * COIN, SwapTypes.XMR_SWAP,
|
||||||
lock_type=SEQUENCE_LOCK_BLOCKS, lock_value=18)
|
lock_type=SEQUENCE_LOCK_BLOCKS, lock_value=18)
|
||||||
self.wait_for_offer(swap_clients[1], offer_id)
|
self.wait_for_offer(swap_clients[1], offer_id)
|
||||||
offer = swap_clients[1].getOffer(offer_id)
|
offer = swap_clients[1].getOffer(offer_id)
|
||||||
@ -676,8 +674,32 @@ class Test(unittest.TestCase):
|
|||||||
self.wait_for_bid(swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
|
self.wait_for_bid(swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
|
||||||
self.wait_for_bid(swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True)
|
self.wait_for_bid(swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True)
|
||||||
|
|
||||||
def pass_06_delay(self):
|
def test_06_multiple_swaps(self):
|
||||||
self.delay_for(60)
|
logging.info('---------- Test Multiple concurrent swaps')
|
||||||
|
swap_clients = self.swap_clients
|
||||||
|
offer1_id = swap_clients[0].postOffer(Coins.BTC, Coins.XMR, 10 * COIN, 100 * XMR_COIN, 10 * COIN, SwapTypes.XMR_SWAP)
|
||||||
|
offer2_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, 10 * COIN, 0.14 * XMR_COIN, 10 * COIN, SwapTypes.XMR_SWAP)
|
||||||
|
|
||||||
|
self.wait_for_offer(swap_clients[1], offer1_id)
|
||||||
|
offer1 = swap_clients[1].getOffer(offer1_id)
|
||||||
|
self.wait_for_offer(swap_clients[1], offer2_id)
|
||||||
|
offer2 = swap_clients[1].getOffer(offer2_id)
|
||||||
|
|
||||||
|
bid1_id = swap_clients[1].postXmrBid(offer1_id, offer1.amount_from)
|
||||||
|
bid2_id = swap_clients[1].postXmrBid(offer2_id, offer2.amount_from)
|
||||||
|
|
||||||
|
self.wait_for_bid(swap_clients[0], bid1_id, BidStates.BID_RECEIVED)
|
||||||
|
swap_clients[0].acceptXmrBid(bid1_id)
|
||||||
|
|
||||||
|
self.wait_for_bid(swap_clients[0], bid2_id, BidStates.BID_RECEIVED)
|
||||||
|
swap_clients[0].acceptXmrBid(bid2_id)
|
||||||
|
|
||||||
|
self.wait_for_bid(swap_clients[0], bid1_id, BidStates.SWAP_COMPLETED, wait_for=180)
|
||||||
|
self.wait_for_bid(swap_clients[1], bid1_id, BidStates.SWAP_COMPLETED, sent=True)
|
||||||
|
|
||||||
|
self.wait_for_bid(swap_clients[0], bid2_id, BidStates.SWAP_COMPLETED, wait_for=180)
|
||||||
|
self.wait_for_bid(swap_clients[1], bid2_id, BidStates.SWAP_COMPLETED, sent=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
eventtypes
|
eventtypes
|
||||||
|
wit
|
||||||
|
Loading…
Reference in New Issue
Block a user