mirror of
https://github.com/basicswap/basicswap.git
synced 2024-12-22 19:49:20 +00:00
ui: Expose offer valid time.
This commit is contained in:
parent
f2018184e7
commit
36a40b5fa3
12 changed files with 131 additions and 64 deletions
|
@ -870,7 +870,7 @@ class BasicSwap(BaseApp):
|
|||
ci.initialiseWallet(key_view, key_spend)
|
||||
root_address = ci.getAddressFromKeys(key_view, key_spend)
|
||||
|
||||
key_str = 'main_wallet_addr_' + chainparams[coin_type]['name']
|
||||
key_str = 'main_wallet_addr_' + ci.coin_name()
|
||||
self.setStringKV(key_str, root_address)
|
||||
return
|
||||
|
||||
|
@ -878,7 +878,7 @@ class BasicSwap(BaseApp):
|
|||
root_hash = ci.getAddressHashFromKey(root_key)[::-1]
|
||||
ci.initialiseWallet(root_key)
|
||||
|
||||
key_str = 'main_wallet_seedid_' + chainparams[coin_type]['name']
|
||||
key_str = 'main_wallet_seedid_' + ci.coin_name()
|
||||
self.setStringKV(key_str, root_hash.hex())
|
||||
|
||||
def setIntKVInSession(self, str_key, int_val, session):
|
||||
|
@ -1101,6 +1101,12 @@ class BasicSwap(BaseApp):
|
|||
else:
|
||||
raise ValueError('Unknown locktype')
|
||||
|
||||
def validateOfferValidTime(self, coin_from, coin_to, valid_for_seconds):
|
||||
if valid_for_seconds < 60 * 60: # SMSG_MIN_TTL
|
||||
raise ValueError('Offer TTL too low')
|
||||
if valid_for_seconds > 48 * 60 * 60:
|
||||
raise ValueError('Offer TTL too high')
|
||||
|
||||
def postOffer(self, coin_from, coin_to, amount, rate, min_bid_amount, swap_type,
|
||||
lock_type=SEQUENCE_LOCK_TIME, lock_value=48 * 60 * 60, auto_accept_bids=False, addr_send_from=None, extra_options={}):
|
||||
# Offer to send offer.amount_from of coin_from in exchange for offer.amount_from * offer.rate of coin_to
|
||||
|
@ -1117,9 +1123,12 @@ class BasicSwap(BaseApp):
|
|||
except Exception:
|
||||
raise ValueError('Unknown coin to type')
|
||||
|
||||
valid_for_seconds = extra_options.get('valid_for_seconds', 60 * 60)
|
||||
|
||||
self.validateSwapType(coin_from_t, coin_to_t, swap_type)
|
||||
self.validateOfferAmounts(coin_from_t, coin_to_t, amount, rate, min_bid_amount)
|
||||
self.validateOfferLockValue(coin_from_t, coin_to_t, lock_type, lock_value)
|
||||
self.validateOfferValidTime(coin_from_t, coin_to_t, valid_for_seconds)
|
||||
|
||||
self.mxDB.acquire()
|
||||
session = None
|
||||
|
@ -1136,7 +1145,7 @@ class BasicSwap(BaseApp):
|
|||
msg_buf.rate = int(rate)
|
||||
msg_buf.min_bid_amount = int(min_bid_amount)
|
||||
|
||||
msg_buf.time_valid = 60 * 60
|
||||
msg_buf.time_valid = valid_for_seconds
|
||||
msg_buf.lock_type = lock_type
|
||||
msg_buf.lock_value = lock_value
|
||||
msg_buf.swap_type = swap_type
|
||||
|
@ -1424,7 +1433,9 @@ class BasicSwap(BaseApp):
|
|||
self.log.info('withdrawCoin %s %s to %s %s', value, self.getTicker(coin_type), addr_to, ' subfee' if subfee else '')
|
||||
|
||||
ci = self.ci(coin_type)
|
||||
return ci.withdrawCoin(value, addr_to, subfee)
|
||||
txid = ci.withdrawCoin(value, addr_to, subfee)
|
||||
self.log.debug('In txn: {}'.format(txid))
|
||||
return txid
|
||||
|
||||
def withdrawParticl(self, type_from, type_to, value, addr_to, subfee):
|
||||
self.log.info('withdrawParticl %s %s to %s %s %s', value, type_from, type_to, addr_to, ' subfee' if subfee else '')
|
||||
|
@ -1435,7 +1446,9 @@ class BasicSwap(BaseApp):
|
|||
type_to = 'part'
|
||||
|
||||
ci = self.ci(Coins.PART)
|
||||
return ci.sendTypeTo(type_from, type_to, value, addr_to, subfee)
|
||||
txid = ci.sendTypeTo(type_from, type_to, value, addr_to, subfee)
|
||||
self.log.debug('In txn: {}'.format(txid))
|
||||
return txid
|
||||
|
||||
def cacheNewAddressForCoin(self, coin_type):
|
||||
self.log.debug('cacheNewAddressForCoin %s', coin_type)
|
||||
|
@ -1449,7 +1462,7 @@ class BasicSwap(BaseApp):
|
|||
if c == Coins.PART:
|
||||
return True # TODO
|
||||
if c == Coins.XMR:
|
||||
expect_address = self.getStringKV('main_wallet_addr_' + chainparams[c]['name'])
|
||||
expect_address = self.getStringKV('main_wallet_addr_' + ci.coin_name())
|
||||
if expect_address is None:
|
||||
self.log.warning('Can\'t find expected main wallet address for coin {}'.format(ci.coin_name()))
|
||||
return False
|
||||
|
@ -1459,7 +1472,7 @@ class BasicSwap(BaseApp):
|
|||
self.log.warning('Wallet for coin {} not derived from swap seed.'.format(ci.coin_name()))
|
||||
return False
|
||||
|
||||
expect_seedid = self.getStringKV('main_wallet_seedid_' + chainparams[c]['name'])
|
||||
expect_seedid = self.getStringKV('main_wallet_seedid_' + ci.coin_name())
|
||||
if expect_seedid is None:
|
||||
self.log.warning('Can\'t find expected wallet seed id for coin {}'.format(ci.coin_name()))
|
||||
return False
|
||||
|
@ -1976,7 +1989,7 @@ class BasicSwap(BaseApp):
|
|||
bid.initiate_txn_refund = bytes.fromhex(refund_txn)
|
||||
|
||||
txid = self.submitTxn(coin_from, txn)
|
||||
self.log.debug('Submitted initiate txn %s to %s chain for bid %s', txid, chainparams[coin_from]['name'], bid_id.hex())
|
||||
self.log.debug('Submitted initiate txn %s to %s chain for bid %s', txid, ci_from.coin_name(), bid_id.hex())
|
||||
bid.initiate_tx = SwapTx(
|
||||
bid_id=bid_id,
|
||||
tx_type=TxTypes.ITX,
|
||||
|
@ -2061,7 +2074,6 @@ class BasicSwap(BaseApp):
|
|||
xmr_swap.b_restore_height = wallet_restore_height
|
||||
self.log.warning('XMR swap restore height clamped to {}'.format(wallet_restore_height))
|
||||
|
||||
|
||||
for_ed25519 = True if coin_to == Coins.XMR else False
|
||||
kbvf = self.getPathKey(coin_from, coin_to, bid_created_at, xmr_swap.contract_count, 1, for_ed25519)
|
||||
kbsf = self.getPathKey(coin_from, coin_to, bid_created_at, xmr_swap.contract_count, 2, for_ed25519)
|
||||
|
@ -3617,6 +3629,7 @@ class BasicSwap(BaseApp):
|
|||
self.validateSwapType(coin_from, coin_to, offer_data.swap_type)
|
||||
self.validateOfferAmounts(coin_from, coin_to, offer_data.amount_from, offer_data.rate, offer_data.min_bid_amount)
|
||||
self.validateOfferLockValue(coin_from, coin_to, offer_data.lock_type, offer_data.lock_value)
|
||||
self.validateOfferValidTime(coin_from, coin_to, offer_data.time_valid)
|
||||
|
||||
assert(offer_data.time_valid >= MIN_OFFER_VALID_TIME and offer_data.time_valid <= MAX_OFFER_VALID_TIME), 'Invalid time_valid'
|
||||
assert(msg['sent'] + offer_data.time_valid >= now), 'Offer expired'
|
||||
|
@ -3629,9 +3642,8 @@ class BasicSwap(BaseApp):
|
|||
elif offer_data.swap_type == SwapTypes.BUYER_FIRST:
|
||||
raise ValueError('TODO')
|
||||
elif offer_data.swap_type == SwapTypes.XMR_SWAP:
|
||||
assert(coin_from != Coins.XMR)
|
||||
assert(coin_from != Coins.PART_ANON)
|
||||
assert(coin_to == Coins.XMR or coin_to == Coins.PART_ANON)
|
||||
assert(coin_from not in (Coins.XMR, Coins.PART_ANON))
|
||||
assert(coin_to in (Coins.XMR, Coins.PART_ANON))
|
||||
self.log.debug('TODO - More restrictions')
|
||||
else:
|
||||
raise ValueError('Unknown swap type {}.'.format(offer_data.swap_type))
|
||||
|
@ -4225,7 +4237,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
a_lock_tx_id = ci_from.getTxHash(xmr_swap.a_lock_tx)
|
||||
a_lock_tx_vout = ci_from.getTxOutputPos(xmr_swap.a_lock_tx, xmr_swap.a_lock_tx_script)
|
||||
self.log.debug('Waiting for lock txn %s to %s chain for bid %s', a_lock_tx_id.hex(), chainparams[coin_from]['name'], bid_id.hex())
|
||||
self.log.debug('Waiting for lock txn %s to %s chain for bid %s', a_lock_tx_id.hex(), ci_from.coin_name(), bid_id.hex())
|
||||
bid.xmr_a_lock_tx = SwapTx(
|
||||
bid_id=bid_id,
|
||||
tx_type=TxTypes.XMR_SWAP_A_LOCK,
|
||||
|
@ -4292,7 +4304,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
vout_pos = ci_from.getTxOutputPos(xmr_swap.a_lock_tx, xmr_swap.a_lock_tx_script)
|
||||
|
||||
self.log.debug('Submitted lock txn %s to %s chain for bid %s', txid_hex, chainparams[coin_from]['name'], bid_id.hex())
|
||||
self.log.debug('Submitted lock txn %s to %s chain for bid %s', txid_hex, ci_from.coin_name(), bid_id.hex())
|
||||
|
||||
bid.xmr_a_lock_tx = SwapTx(
|
||||
bid_id=bid_id,
|
||||
|
@ -4356,7 +4368,7 @@ class BasicSwap(BaseApp):
|
|||
self.logBidEvent(bid, EventLogTypes.FAILED_TX_B_LOCK_PUBLISH, str_error, session)
|
||||
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(), ci_to.coin_name(), bid_id.hex())
|
||||
bid.xmr_b_lock_tx = SwapTx(
|
||||
bid_id=bid_id,
|
||||
tx_type=TxTypes.XMR_SWAP_B_LOCK,
|
||||
|
@ -4435,7 +4447,7 @@ class BasicSwap(BaseApp):
|
|||
xmr_swap.a_lock_spend_tx = ci_from.setTxSignature(xmr_swap.a_lock_spend_tx, witness_stack)
|
||||
|
||||
txid = bytes.fromhex(ci_from.publishTx(xmr_swap.a_lock_spend_tx))
|
||||
self.log.debug('Submitted lock spend txn %s to %s chain for bid %s', txid.hex(), chainparams[coin_from]['name'], bid_id.hex())
|
||||
self.log.debug('Submitted lock spend txn %s to %s chain for bid %s', txid.hex(), ci_from.coin_name(), bid_id.hex())
|
||||
bid.xmr_a_lock_spend_tx = SwapTx(
|
||||
bid_id=bid_id,
|
||||
tx_type=TxTypes.XMR_SWAP_A_LOCK_SPEND,
|
||||
|
@ -4980,7 +4992,7 @@ class BasicSwap(BaseApp):
|
|||
rv = {
|
||||
'version': self.coin_clients[coin]['core_version'],
|
||||
'deposit_address': self.getCachedAddressForCoin(coin),
|
||||
'name': chainparams[coin]['name'].capitalize(),
|
||||
'name': ci.coin_name().capitalize(),
|
||||
'blocks': blockchaininfo['blocks'],
|
||||
'balance': format_amount(make_int(walletinfo['balance'], scale), scale),
|
||||
'unconfirmed': format_amount(make_int(walletinfo.get('unconfirmed_balance'), scale), scale),
|
||||
|
|
|
@ -37,6 +37,7 @@ chainparams = {
|
|||
'pubkey_address': 0x38,
|
||||
'script_address': 0x3c,
|
||||
'key_prefix': 0x6c,
|
||||
'stealth_key_prefix': 0x14,
|
||||
'hrp': 'pw',
|
||||
'bip44': 44,
|
||||
'min_amount': 1000,
|
||||
|
@ -47,6 +48,7 @@ chainparams = {
|
|||
'pubkey_address': 0x76,
|
||||
'script_address': 0x7a,
|
||||
'key_prefix': 0x2e,
|
||||
'stealth_key_prefix': 0x15,
|
||||
'hrp': 'tpw',
|
||||
'bip44': 1,
|
||||
'min_amount': 1000,
|
||||
|
@ -57,6 +59,7 @@ chainparams = {
|
|||
'pubkey_address': 0x76,
|
||||
'script_address': 0x7a,
|
||||
'key_prefix': 0x2e,
|
||||
'stealth_key_prefix': 0x15,
|
||||
'hrp': 'rtpw',
|
||||
'bip44': 1,
|
||||
'min_amount': 1000,
|
||||
|
|
|
@ -33,42 +33,42 @@ G = Point(curve_secp256k1, ep.Gx, ep.Gy, ep.o)
|
|||
SECP256K1_ORDER_HALF = ep.o // 2
|
||||
|
||||
|
||||
def ToDER(P):
|
||||
def ToDER(P) -> bytes:
|
||||
return bytes((4, )) + int(P.x()).to_bytes(32, byteorder='big') + int(P.y()).to_bytes(32, byteorder='big')
|
||||
|
||||
|
||||
def bytes32ToInt(b):
|
||||
def bytes32ToInt(b) -> int:
|
||||
return int.from_bytes(b, byteorder='big')
|
||||
|
||||
|
||||
def intToBytes32(i):
|
||||
def intToBytes32(i: int) -> bytes:
|
||||
return i.to_bytes(32, byteorder='big')
|
||||
|
||||
|
||||
def intToBytes32_le(i):
|
||||
def intToBytes32_le(i: int) -> bytes:
|
||||
return i.to_bytes(32, byteorder='little')
|
||||
|
||||
|
||||
def bytesToHexStr(b):
|
||||
def bytesToHexStr(b: bytes) -> str:
|
||||
return codecs.encode(b, 'hex').decode('utf-8')
|
||||
|
||||
|
||||
def hexStrToBytes(h):
|
||||
def hexStrToBytes(h: str) -> bytes:
|
||||
if h.startswith('0x'):
|
||||
h = h[2:]
|
||||
return bytes.fromhex(h)
|
||||
|
||||
|
||||
def getSecretBytes():
|
||||
def getSecretBytes() -> bytes:
|
||||
i = 1 + secrets.randbelow(ep.o - 1)
|
||||
return intToBytes32(i)
|
||||
|
||||
|
||||
def getSecretInt():
|
||||
def getSecretInt() -> int:
|
||||
return 1 + secrets.randbelow(ep.o - 1)
|
||||
|
||||
|
||||
def getInsecureBytes():
|
||||
def getInsecureBytes() -> bytes:
|
||||
while True:
|
||||
s = os.urandom(32)
|
||||
|
||||
|
@ -77,7 +77,7 @@ def getInsecureBytes():
|
|||
return s
|
||||
|
||||
|
||||
def getInsecureInt():
|
||||
def getInsecureInt() -> int:
|
||||
while True:
|
||||
s = os.urandom(32)
|
||||
|
||||
|
@ -86,7 +86,7 @@ def getInsecureInt():
|
|||
return s_test
|
||||
|
||||
|
||||
def powMod(x, y, z):
|
||||
def powMod(x, y, z) -> int:
|
||||
# Calculate (x ** y) % z efficiently.
|
||||
number = 1
|
||||
while y:
|
||||
|
|
|
@ -66,11 +66,14 @@ def getCoinName(c):
|
|||
def listAvailableCoins(swap_client):
|
||||
coins = []
|
||||
for k, v in swap_client.coin_clients.items():
|
||||
if k not in chainparams:
|
||||
continue
|
||||
if v['connection_type'] == 'rpc':
|
||||
coins.append((int(k), getCoinName(k)))
|
||||
|
||||
if k == Coins.PART:
|
||||
coins.append((int(Coins.PART_ANON), getCoinName(k)))
|
||||
pass
|
||||
# TODO: Uncomment
|
||||
# coins.append((int(Coins.PART_ANON), getCoinName(k)))
|
||||
return coins
|
||||
|
||||
|
||||
|
@ -402,14 +405,17 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
page_data['coin_to'] = getCoinType(get_data_entry(form_data, 'coin_to'))
|
||||
coin_to = Coins(page_data['coin_to'])
|
||||
ci_to = swap_client.ci(coin_to)
|
||||
if coin_to != Coins.XMR:
|
||||
page_data['fee_to_conf'] = ci_to._conf_target # Set default value
|
||||
parsed_data['coin_to'] = coin_to
|
||||
if coin_to == Coins.XMR:
|
||||
page_data['swap_style'] = 'xmr'
|
||||
else:
|
||||
page_data['swap_style'] = 'atomic'
|
||||
except Exception:
|
||||
errors.append('Unknown Coin To')
|
||||
|
||||
if parsed_data['coin_to'] in (Coins.XMR, Coins.PART_ANON):
|
||||
page_data['swap_style'] = 'xmr'
|
||||
else:
|
||||
page_data['swap_style'] = 'atomic'
|
||||
|
||||
try:
|
||||
page_data['amt_from'] = get_data_entry(form_data, 'amt_from')
|
||||
parsed_data['amt_from'] = inputAmount(page_data['amt_from'], ci_from)
|
||||
|
@ -460,6 +466,12 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
elif have_data_entry(form_data, 'lockseconds'):
|
||||
parsed_data['lock_seconds'] = int(get_data_entry(form_data, 'lockseconds'))
|
||||
|
||||
if have_data_entry(form_data, 'validhrs'):
|
||||
page_data['validhrs'] = int(get_data_entry(form_data, 'validhrs'))
|
||||
parsed_data['valid_for_seconds'] = page_data['validhrs'] * 60 * 60
|
||||
elif have_data_entry(form_data, 'valid_for_seconds'):
|
||||
parsed_data['valid_for_seconds'] = int(get_data_entry(form_data, 'valid_for_seconds'))
|
||||
|
||||
page_data['autoaccept'] = True if have_data_entry(form_data, 'autoaccept') else False
|
||||
parsed_data['autoaccept'] = page_data['autoaccept']
|
||||
|
||||
|
@ -499,7 +511,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
swap_client = self.server.swap_client
|
||||
|
||||
swap_type = SwapTypes.SELLER_FIRST
|
||||
if parsed_data['coin_to'] == Coins.XMR:
|
||||
if parsed_data['coin_to'] in (Coins.XMR, Coins.PART_ANON):
|
||||
swap_type = SwapTypes.XMR_SWAP
|
||||
|
||||
if swap_client.coin_clients[parsed_data['coin_from']]['use_csv'] and swap_client.coin_clients[parsed_data['coin_to']]['use_csv']:
|
||||
|
@ -522,6 +534,8 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
extra_options['to_fee_multiplier_percent'] = parsed_data['fee_to_extra']
|
||||
if 'to_fee_override' in parsed_data:
|
||||
extra_options['to_fee_override'] = parsed_data['to_fee_override']
|
||||
if 'valid_for_seconds' in parsed_data:
|
||||
extra_options['valid_for_seconds'] = parsed_data['valid_for_seconds']
|
||||
|
||||
offer_id = swap_client.postOffer(
|
||||
parsed_data['coin_from'],
|
||||
|
@ -552,6 +566,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
# Set defaults
|
||||
'fee_from_conf': 2,
|
||||
'fee_to_conf': 2,
|
||||
'validhrs': 1,
|
||||
'lockhrs': 32,
|
||||
'autoaccept': True
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ from coincurve.ecdsaotves import (
|
|||
ecdsaotves_rec_enc_key)
|
||||
|
||||
from .ecc_util import (
|
||||
G, ep,
|
||||
ep,
|
||||
pointToCPK, CPKToPoint,
|
||||
getSecretInt,
|
||||
b2h, i2b, b2i, i2h)
|
||||
|
@ -92,23 +92,23 @@ class BTCInterface(CoinInterface):
|
|||
return COIN
|
||||
|
||||
@staticmethod
|
||||
def exp():
|
||||
def exp() -> int:
|
||||
return 8
|
||||
|
||||
@staticmethod
|
||||
def nbk():
|
||||
def nbk() -> int:
|
||||
return 32
|
||||
|
||||
@staticmethod
|
||||
def nbK(): # No. of bytes requires to encode a public key
|
||||
def nbK() -> int: # No. of bytes requires to encode a public key
|
||||
return 33
|
||||
|
||||
@staticmethod
|
||||
def witnessScaleFactor():
|
||||
def witnessScaleFactor() -> int:
|
||||
return 4
|
||||
|
||||
@staticmethod
|
||||
def txVersion():
|
||||
def txVersion() -> int:
|
||||
return 2
|
||||
|
||||
@staticmethod
|
||||
|
@ -119,11 +119,11 @@ class BTCInterface(CoinInterface):
|
|||
return rv
|
||||
|
||||
@staticmethod
|
||||
def compareFeeRates(a, b):
|
||||
def compareFeeRates(a, b) -> bool:
|
||||
return abs(a - b) < 20
|
||||
|
||||
@staticmethod
|
||||
def xmr_swap_alock_spend_tx_vsize():
|
||||
def xmr_swap_alock_spend_tx_vsize() -> int:
|
||||
return 147
|
||||
|
||||
@staticmethod
|
||||
|
@ -921,7 +921,7 @@ class BTCInterface(CoinInterface):
|
|||
rv = pubkey.verify_compact(sig, message_hash, hasher=None)
|
||||
assert(rv is True)
|
||||
|
||||
def verifyMessage(self, address, message, signature, message_magic=None):
|
||||
def verifyMessage(self, address, message, signature, message_magic=None) -> bool:
|
||||
if message_magic is None:
|
||||
message_magic = chainparams[self.coin_type()]['message_magic']
|
||||
|
||||
|
|
|
@ -15,8 +15,9 @@ from .contrib.test_framework.script import (
|
|||
OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG
|
||||
)
|
||||
|
||||
from .util import encodeStealthAddress
|
||||
from .chainparams import Coins, chainparams
|
||||
from .interface_btc import BTCInterface
|
||||
from .chainparams import Coins
|
||||
|
||||
|
||||
class BalanceTypes(IntEnum):
|
||||
|
@ -35,22 +36,22 @@ class PARTInterface(BTCInterface):
|
|||
return BalanceTypes.PLAIN
|
||||
|
||||
@staticmethod
|
||||
def witnessScaleFactor():
|
||||
def witnessScaleFactor() -> int:
|
||||
return 2
|
||||
|
||||
@staticmethod
|
||||
def txVersion():
|
||||
def txVersion() -> int:
|
||||
return 0xa0
|
||||
|
||||
@staticmethod
|
||||
def xmr_swap_alock_spend_tx_vsize():
|
||||
def xmr_swap_alock_spend_tx_vsize() -> int:
|
||||
return 213
|
||||
|
||||
@staticmethod
|
||||
def txoType():
|
||||
return CTxOutPart
|
||||
|
||||
def setDefaults(self):
|
||||
def setDefaults(self) -> None:
|
||||
super().setDefaults()
|
||||
self._anon_tx_ring_size = 8 # TODO: Make option
|
||||
|
||||
|
@ -86,6 +87,11 @@ class PARTInterface(BTCInterface):
|
|||
def getScriptForPubkeyHash(self, pkh):
|
||||
return CScript([OP_DUP, OP_HASH160, pkh, OP_EQUALVERIFY, OP_CHECKSIG])
|
||||
|
||||
def formatStealthAddress(self, scan_pubkey, spend_pubkey):
|
||||
prefix_byte = chainparams[self.coin_type()][self._network]['stealth_key_prefix']
|
||||
|
||||
return encodeStealthAddress(prefix_byte, scan_pubkey, spend_pubkey)
|
||||
|
||||
|
||||
class PARTInterfaceBlind(PARTInterface):
|
||||
@staticmethod
|
||||
|
@ -99,7 +105,17 @@ class PARTInterfaceAnon(PARTInterface):
|
|||
return BalanceTypes.ANON
|
||||
|
||||
def publishBLockTx(self, Kbv, Kbs, output_amount, feerate):
|
||||
raise ValueError('TODO - new core release')
|
||||
sx_addr = self.formatStealthAddress(Kbv, Kbs)
|
||||
self._log.debug('sx_addr: {}'.format(sx_addr))
|
||||
|
||||
# TODO: Fund from other balances
|
||||
params = ['anon', 'anon',
|
||||
[{'address': sx_addr, 'amount': self.format_amount(output_amount)}, ],
|
||||
'', '', self._anon_tx_ring_size, 1, False,
|
||||
{'conf_target': self._conf_target, 'blind_watchonly_visible': True}]
|
||||
|
||||
txid = self.rpc_callback('sendtypeto', params)
|
||||
return bytes.fromhex(txid)
|
||||
|
||||
def findTxB(self, kbv, Kbs, cb_swap_value, cb_block_confirmed, restore_height):
|
||||
raise ValueError('TODO - new core release')
|
||||
|
|
|
@ -47,15 +47,15 @@ class XMRInterface(CoinInterface):
|
|||
return XMR_COIN
|
||||
|
||||
@staticmethod
|
||||
def exp():
|
||||
def exp() -> int:
|
||||
return 12
|
||||
|
||||
@staticmethod
|
||||
def nbk():
|
||||
def nbk() -> int:
|
||||
return 32
|
||||
|
||||
@staticmethod
|
||||
def nbK(): # No. of bytes requires to encode a public key
|
||||
def nbK() -> int: # No. of bytes requires to encode a public key
|
||||
return 32
|
||||
|
||||
def __init__(self, coin_settings, network, swap_client=None):
|
||||
|
|
|
@ -54,7 +54,8 @@
|
|||
</select></td></tr>
|
||||
{% endif %}
|
||||
|
||||
<tr class="padded_row"><td>Contract locked (hrs)</td><td><input type="number" name="lockhrs" min="1" max="64" value="{{ data.lockhrs }}" readonly></td>{% if data.swap_style != 'xmr' %}<td colspan=2>Participate txn will be locked for half the time.</td>{% endif %}</tr>
|
||||
<tr class="padded_row"><td>Offer valid (hrs)</td><td><input type="number" name="validhrs" min="1" max="48" value="{{ data.validhrs }}" readonly></td></tr>
|
||||
<tr><td>Contract locked (hrs)</td><td><input type="number" name="lockhrs" min="1" max="64" value="{{ data.lockhrs }}" readonly></td>{% if data.swap_style != 'xmr' %}<td colspan=2>Participate txn will be locked for half the time.</td>{% endif %}</tr>
|
||||
<tr><td>Auto Accept Bids</td><td colspan=3><input type="checkbox" name="autoaccept_" value="aa" {% if data.autoaccept==true %} checked="true"{% endif %} disabled></td></tr>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -51,7 +51,8 @@
|
|||
</select></td></tr>
|
||||
{% endif %}
|
||||
|
||||
<tr class="padded_row"><td>Contract locked (hrs)</td><td><input type="number" name="lockhrs" min="1" max="96" value="{{ data.lockhrs }}"></td><td colspan=2>Participate txn will be locked for half the time.</td></tr>
|
||||
<tr class="padded_row"><td>Offer valid (hrs)</td><td><input type="number" name="validhrs" min="1" max="48" value="{{ data.validhrs }}"></td></tr>
|
||||
<tr><td>Contract locked (hrs)</td><td><input type="number" name="lockhrs" min="1" max="96" value="{{ data.lockhrs }}"></td>{% if data.swap_style != 'xmr' %}<td colspan=2>Participate txn will be locked for half the time.</td>{% endif %}</tr>
|
||||
<tr><td>Auto Accept Bids</td><td colspan=3><input type="checkbox" name="autoaccept" value="aa" {% if data.autoaccept==true %} checked="true"{% endif %}></td></tr>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ def assert_cond(v, err='Bad opcode'):
|
|||
raise ValueError(err)
|
||||
|
||||
|
||||
def toBool(s):
|
||||
def toBool(s) -> bool:
|
||||
return s.lower() in ["1", "true"]
|
||||
|
||||
|
||||
|
@ -170,7 +170,7 @@ def SerialiseNum(n):
|
|||
return bytes((len(rv),)) + rv
|
||||
|
||||
|
||||
def DeserialiseNum(b, o=0):
|
||||
def DeserialiseNum(b, o=0) -> int:
|
||||
if b[o] == 0:
|
||||
return 0
|
||||
if b[o] > 0x50 and b[o] <= 0x50 + 16:
|
||||
|
@ -276,7 +276,7 @@ def make_int(v, scale=8, r=0): # r = 0, no rounding, fail, r > 0 round up, r <
|
|||
return rv
|
||||
|
||||
|
||||
def validate_amount(amount, scale=8):
|
||||
def validate_amount(amount, scale=8) -> bool:
|
||||
str_amount = float_to_str(amount) if type(amount) == float else str(amount)
|
||||
has_decimal = False
|
||||
for c in str_amount:
|
||||
|
@ -324,3 +324,16 @@ def getP2SHScriptForHash(p2sh):
|
|||
|
||||
def getP2WSH(script):
|
||||
return bytes((OpCodes.OP_0, 0x20)) + hashlib.sha256(script).digest()
|
||||
|
||||
|
||||
def encodeStealthAddress(prefix_byte, scan_pubkey, spend_pubkey):
|
||||
data = bytes((0x00,))
|
||||
data += scan_pubkey
|
||||
data += bytes((0x01,))
|
||||
data += spend_pubkey
|
||||
data += bytes((0x00,)) # number_signatures - unused
|
||||
data += bytes((0x00,)) # num prefix bits
|
||||
|
||||
b = bytes((prefix_byte,)) + data
|
||||
b += hashlib.sha256(hashlib.sha256(b).digest()).digest()[:4]
|
||||
return b58encode(b)
|
||||
|
|
|
@ -235,6 +235,7 @@ def wait_for_balance(delay_event, url, balance_key, expect_amount, iterations=20
|
|||
i = 0
|
||||
while not delay_event.is_set():
|
||||
rv_js = json.loads(urlopen(url).read())
|
||||
print("[rm] rv_js", rv_js)
|
||||
if float(rv_js[balance_key]) >= expect_amount:
|
||||
break
|
||||
delay_event.wait(delay_time)
|
||||
|
|
|
@ -703,9 +703,10 @@ class Test(unittest.TestCase):
|
|||
js_1 = json.loads(urlopen('http://127.0.0.1:1801/json/wallets/part').read())
|
||||
assert(float(js_1['balance']) > 200.0)
|
||||
|
||||
callnoderpc(1, 'reservebalance', [True, 1000000]) # Stop staking to avoid conflicts (input used by tx->anon staked before tx gets in the chain)
|
||||
post_json = {
|
||||
'value': 100,
|
||||
'address': js_0['stealth_address'],
|
||||
'address': js_1['stealth_address'],
|
||||
'subfee': False,
|
||||
'type_to': 'anon',
|
||||
}
|
||||
|
@ -718,8 +719,13 @@ class Test(unittest.TestCase):
|
|||
assert(len(json_rv['txid']) == 64)
|
||||
|
||||
logging.info('Waiting for anon balance')
|
||||
wait_for_balance(test_delay_event, 'http://127.0.0.1:1800/json/wallets/part', 'anon_balance', 110.0)
|
||||
try:
|
||||
wait_for_balance(test_delay_event, 'http://127.0.0.1:1801/json/wallets/part', 'anon_balance', 110.0)
|
||||
except Exception as e:
|
||||
ft = callnoderpc(0, 'filtertransactions', [{'count': 0}])
|
||||
raise e
|
||||
|
||||
callnoderpc(1, 'reservebalance', [False])
|
||||
post_json = {
|
||||
'value': 10,
|
||||
'address': js_0['stealth_address'],
|
||||
|
@ -727,7 +733,7 @@ class Test(unittest.TestCase):
|
|||
'type_from': 'anon',
|
||||
'type_to': 'blind',
|
||||
}
|
||||
json_rv = json.loads(post_json_req('http://127.0.0.1:1800/json/wallets/part/withdraw', post_json))
|
||||
json_rv = json.loads(post_json_req('http://127.0.0.1:1801/json/wallets/part/withdraw', post_json))
|
||||
assert(len(json_rv['txid']) == 64)
|
||||
|
||||
logging.info('Waiting for blind balance')
|
||||
|
@ -735,14 +741,13 @@ class Test(unittest.TestCase):
|
|||
if float(js_0['blind_balance']) >= 10.0:
|
||||
raise ValueError('Expect blind balance < 10')
|
||||
|
||||
logging.warning('TODO')
|
||||
return
|
||||
return # TODO
|
||||
|
||||
amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
|
||||
rate_swap = make_int(random.uniform(2.0, 20.0), scale=8, r=1)
|
||||
offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.PART_ANON, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP)
|
||||
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
|
||||
offers = swap_clients[1].listOffers(filters={'offer_id': offer_id})
|
||||
offers = swap_clients[0].listOffers(filters={'offer_id': offer_id})
|
||||
offer = offers[0]
|
||||
|
||||
bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from)
|
||||
|
|
Loading…
Reference in a new issue