ui: Expose Particl blinded and anon balances.
This commit is contained in:
parent
dd37156e65
commit
b1ea76dcb6
@ -534,6 +534,7 @@ class BasicSwap(BaseApp):
|
||||
self.zmqSubscriber.setsockopt_string(zmq.SUBSCRIBE, 'smsg')
|
||||
|
||||
for c in Coins:
|
||||
if c in chainparams:
|
||||
self.setCoinConnectParams(c)
|
||||
|
||||
if self.chain == 'mainnet':
|
||||
@ -711,6 +712,8 @@ class BasicSwap(BaseApp):
|
||||
self.upgradeDatabase(self.db_version)
|
||||
|
||||
for c in Coins:
|
||||
if not c in chainparams:
|
||||
continue
|
||||
self.setCoinRunParams(c)
|
||||
self.createCoinInterface(c)
|
||||
|
||||
@ -777,6 +780,8 @@ class BasicSwap(BaseApp):
|
||||
|
||||
def stopDaemons(self):
|
||||
for c in Coins:
|
||||
if not c in chainparams:
|
||||
continue
|
||||
chain_client_settings = self.getChainClientSettings(c)
|
||||
if self.coin_clients[c]['connection_type'] == 'rpc' and chain_client_settings['manage_daemon'] is True:
|
||||
self.stopDaemon(c)
|
||||
@ -1382,7 +1387,7 @@ class BasicSwap(BaseApp):
|
||||
self.mxDB.release()
|
||||
|
||||
def getReceiveAddressForCoin(self, coin_type):
|
||||
new_addr = self.coin_clients[coin_type]['interface'].getNewAddress(self.coin_clients[coin_type]['use_segwit'])
|
||||
new_addr = self.ci(coin_type).getNewAddress(self.coin_clients[coin_type]['use_segwit'])
|
||||
self.log.debug('Generated new receive address %s for %s', new_addr, str(coin_type))
|
||||
return new_addr
|
||||
|
||||
@ -1412,6 +1417,17 @@ class BasicSwap(BaseApp):
|
||||
ci = self.ci(coin_type)
|
||||
return ci.withdrawCoin(value, addr_to, subfee)
|
||||
|
||||
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 '')
|
||||
|
||||
if type_from == 'plain':
|
||||
type_from = 'part'
|
||||
if type_to == 'plain':
|
||||
type_to = 'part'
|
||||
|
||||
ci = self.ci(Coins.PART)
|
||||
return ci.sendTypeTo(type_from, type_to, value, addr_to, subfee)
|
||||
|
||||
def cacheNewAddressForCoin(self, coin_type):
|
||||
self.log.debug('cacheNewAddressForCoin %s', coin_type)
|
||||
key_str = 'receive_addr_' + chainparams[coin_type]['name']
|
||||
@ -1483,6 +1499,31 @@ class BasicSwap(BaseApp):
|
||||
self.mxDB.release()
|
||||
return addr
|
||||
|
||||
def getCachedStealthAddressForCoin(self, coin_type):
|
||||
self.log.debug('getCachedStealthAddressForCoin %s', coin_type)
|
||||
# TODO: auto refresh after used
|
||||
|
||||
ci = self.ci(coin_type)
|
||||
key_str = 'stealth_addr_' + ci.coin_name()
|
||||
self.mxDB.acquire()
|
||||
try:
|
||||
session = scoped_session(self.session_factory)
|
||||
try:
|
||||
addr = session.query(DBKVString).filter_by(key=key_str).first().value
|
||||
except Exception:
|
||||
addr = ci.getNewStealthAddress()
|
||||
self.log.info('Generated new stealth address for %s', coin_type)
|
||||
session.add(DBKVString(
|
||||
key=key_str,
|
||||
value=addr
|
||||
))
|
||||
session.commit()
|
||||
finally:
|
||||
session.close()
|
||||
session.remove()
|
||||
self.mxDB.release()
|
||||
return addr
|
||||
|
||||
def getNewContractId(self):
|
||||
self.mxDB.acquire()
|
||||
try:
|
||||
@ -4850,11 +4891,20 @@ class BasicSwap(BaseApp):
|
||||
'synced': '{0:.2f}'.format(round(blockchaininfo['verificationprogress'], 2)),
|
||||
'expected_seed': ci.knownWalletSeed(),
|
||||
}
|
||||
|
||||
if coin == Coins.PART:
|
||||
rv['anon_balance'] = walletinfo['anon_balance']
|
||||
rv['anon_unconfirmed'] = walletinfo['unconfirmed_anon']
|
||||
rv['blind_balance'] = walletinfo['blind_balance']
|
||||
rv['blind_unconfirmed'] = walletinfo['unconfirmed_blind']
|
||||
|
||||
return rv
|
||||
|
||||
def getWalletsInfo(self, opts=None):
|
||||
rv = {}
|
||||
for c in Coins:
|
||||
if not c in chainparams:
|
||||
continue
|
||||
if self.coin_clients[c]['connection_type'] == 'rpc':
|
||||
try:
|
||||
rv[c] = self.getWalletInfo(c)
|
||||
|
@ -21,6 +21,8 @@ class Coins(IntEnum):
|
||||
# DCR = 4
|
||||
NMC = 5
|
||||
XMR = 6
|
||||
PART_BLIND = 7
|
||||
PART_ANON = 8
|
||||
|
||||
|
||||
chainparams = {
|
||||
@ -202,6 +204,10 @@ chainparams = {
|
||||
class CoinInterface:
|
||||
def __init__(self):
|
||||
self._unknown_wallet_seed = True
|
||||
self.setDefaults()
|
||||
|
||||
def setDefaults(self):
|
||||
pass
|
||||
|
||||
def make_int(self, amount_in, r=0):
|
||||
return make_int(amount_in, self.exp(), r=r)
|
||||
|
@ -76,6 +76,8 @@ def extractDomain(url):
|
||||
def listAvailableExplorers(swap_client):
|
||||
explorers = []
|
||||
for c in Coins:
|
||||
if not c in chainparams:
|
||||
continue
|
||||
for i, e in enumerate(swap_client.coin_clients[c]['explorers']):
|
||||
explorers.append(('{}_{}'.format(int(c), i), swap_client.coin_clients[c]['name'].capitalize() + ' - ' + extractDomain(e.base_url)))
|
||||
return explorers
|
||||
@ -213,10 +215,13 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
def page_wallets(self, url_split, post_string):
|
||||
swap_client = self.server.swap_client
|
||||
|
||||
page_data = {}
|
||||
messages = []
|
||||
form_data = self.checkForm(post_string, 'wallets', messages)
|
||||
if form_data:
|
||||
for c in Coins:
|
||||
if not c in chainparams:
|
||||
continue
|
||||
cid = str(int(c))
|
||||
|
||||
if bytes('newaddr_' + cid, 'utf-8') in form_data:
|
||||
@ -228,12 +233,43 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
except Exception as ex:
|
||||
messages.append('Reseed failed ' + str(ex))
|
||||
elif bytes('withdraw_' + cid, 'utf-8') in form_data:
|
||||
try:
|
||||
value = form_data[bytes('amt_' + cid, 'utf-8')][0].decode('utf-8')
|
||||
page_data['wd_value_' + cid] = value
|
||||
except Exception as e:
|
||||
messages.append('Error: Missing value')
|
||||
try:
|
||||
address = form_data[bytes('to_' + cid, 'utf-8')][0].decode('utf-8')
|
||||
page_data['wd_address_' + cid] = address
|
||||
except Exception as e:
|
||||
messages.append('Error: Missing address')
|
||||
|
||||
subfee = True if bytes('subfee_' + cid, 'utf-8') in form_data else False
|
||||
txid = swap_client.withdrawCoin(c, value, address, subfee)
|
||||
page_data['wd_subfee_' + cid] = subfee
|
||||
|
||||
if c == Coins.PART:
|
||||
try:
|
||||
type_from = form_data[bytes('withdraw_type_from_' + cid, 'utf-8')][0].decode('utf-8')
|
||||
type_to = form_data[bytes('withdraw_type_to_' + cid, 'utf-8')][0].decode('utf-8')
|
||||
page_data['wd_type_from_' + cid] = type_from
|
||||
page_data['wd_type_to_' + cid] = type_to
|
||||
except Exception as e:
|
||||
messages.append('Error: Missing type')
|
||||
|
||||
if len(messages) == 0:
|
||||
ticker = swap_client.getTicker(c)
|
||||
if c == Coins.PART:
|
||||
try:
|
||||
txid = swap_client.withdrawParticl(type_from, type_to, value, address, subfee)
|
||||
messages.append('Withdrew {} {} ({} to {}) to address {}<br/>In txid: {}'.format(value, ticker, type_from, type_to, address, txid))
|
||||
except Exception as e:
|
||||
messages.append('Error: {}'.format(str(e)))
|
||||
else:
|
||||
try:
|
||||
txid = swap_client.withdrawCoin(c, value, address, subfee)
|
||||
messages.append('Withdrew {} {} to address {}<br/>In txid: {}'.format(value, ticker, address, txid))
|
||||
except Exception as e:
|
||||
messages.append('Error: {}'.format(str(e)))
|
||||
|
||||
wallets = swap_client.getWalletsInfo()
|
||||
|
||||
@ -249,10 +285,11 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
ci = swap_client.ci(k)
|
||||
fee_rate, fee_src = swap_client.getFeeRateForCoin(k)
|
||||
est_fee = swap_client.estimateWithdrawFee(k, fee_rate)
|
||||
wallets_formatted.append({
|
||||
cid = str(int(k))
|
||||
wf = {
|
||||
'name': w['name'],
|
||||
'version': w['version'],
|
||||
'cid': str(int(k)),
|
||||
'cid': cid,
|
||||
'fee_rate': ci.format_amount(int(fee_rate * ci.COIN())),
|
||||
'fee_rate_src': fee_src,
|
||||
'est_fee': 'Unknown' if est_fee is None else ci.format_amount(int(est_fee * ci.COIN())),
|
||||
@ -262,9 +299,32 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
'deposit_address': w['deposit_address'],
|
||||
'expected_seed': w['expected_seed'],
|
||||
'balance_all': float(w['balance']) + float(w['unconfirmed']),
|
||||
})
|
||||
}
|
||||
if float(w['unconfirmed']) > 0.0:
|
||||
wallets_formatted[-1]['unconfirmed'] = w['unconfirmed']
|
||||
wf['unconfirmed'] = w['unconfirmed']
|
||||
|
||||
if k == Coins.PART:
|
||||
wf['stealth_address'] = swap_client.getCachedStealthAddressForCoin(Coins.PART)
|
||||
wf['blind_balance'] = w['blind_balance']
|
||||
if float(w['blind_unconfirmed']) > 0.0:
|
||||
wf['blind_unconfirmed'] = w['blind_unconfirmed']
|
||||
wf['anon_balance'] = w['anon_balance']
|
||||
if float(w['anon_unconfirmed']) > 0.0:
|
||||
wf['anon_unconfirmed'] = w['anon_unconfirmed']
|
||||
|
||||
if 'wd_type_from_' + cid in page_data:
|
||||
wf['wd_type_from'] = page_data['wd_type_from_' + cid]
|
||||
if 'wd_type_to_' + cid in page_data:
|
||||
wf['wd_type_to'] = page_data['wd_type_to_' + cid]
|
||||
|
||||
if 'wd_value_' + cid in page_data:
|
||||
wf['wd_value'] = page_data['wd_value_' + cid]
|
||||
if 'wd_address_' + cid in page_data:
|
||||
wf['wd_address'] = page_data['wd_address_' + cid]
|
||||
if 'wd_subfee_' + cid in page_data:
|
||||
wf['wd_subfee'] = page_data['wd_subfee_' + cid]
|
||||
|
||||
wallets_formatted.append(wf)
|
||||
|
||||
template = env.get_template('wallets.html')
|
||||
return bytes(template.render(
|
||||
|
@ -5,6 +5,8 @@
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
from enum import IntEnum
|
||||
|
||||
from .contrib.test_framework.messages import (
|
||||
CTxOutPart,
|
||||
)
|
||||
@ -17,11 +19,21 @@ from .interface_btc import BTCInterface
|
||||
from .chainparams import Coins
|
||||
|
||||
|
||||
class BalanceTypes(IntEnum):
|
||||
PLAIN = 1
|
||||
BLIND = 2
|
||||
ANON = 3
|
||||
|
||||
|
||||
class PARTInterface(BTCInterface):
|
||||
@staticmethod
|
||||
def coin_type():
|
||||
return Coins.PART
|
||||
|
||||
@staticmethod
|
||||
def balance_type():
|
||||
return BalanceTypes.PLAIN
|
||||
|
||||
@staticmethod
|
||||
def witnessScaleFactor():
|
||||
return 2
|
||||
@ -38,6 +50,10 @@ class PARTInterface(BTCInterface):
|
||||
def txoType():
|
||||
return CTxOutPart
|
||||
|
||||
def setDefaults(self):
|
||||
super().setDefaults()
|
||||
self._anon_tx_ring_size = 8 # TODO: Make option
|
||||
|
||||
def knownWalletSeed(self):
|
||||
# TODO: Double check
|
||||
return True
|
||||
@ -45,6 +61,9 @@ class PARTInterface(BTCInterface):
|
||||
def getNewAddress(self, use_segwit):
|
||||
return self.rpc_callback('getnewaddress', ['swap_receive'])
|
||||
|
||||
def getNewStealthAddress(self):
|
||||
return self.rpc_callback('getnewstealthaddress', ['swap_stealth'])
|
||||
|
||||
def haveSpentIndex(self):
|
||||
version = self.getDaemonVersion()
|
||||
index_info = self.rpc_callback('getinsightinfo' if int(str(version)[:2]) > 19 else 'getindexinfo')
|
||||
@ -57,5 +76,25 @@ class PARTInterface(BTCInterface):
|
||||
params = [addr_to, value, '', '', subfee, '', True, self._conf_target]
|
||||
return self.rpc_callback('sendtoaddress', params)
|
||||
|
||||
def sendTypeTo(self, type_from, type_to, value, addr_to, subfee):
|
||||
params = [type_from, type_to,
|
||||
[{'address': addr_to, 'amount': value, 'subfee': subfee}, ],
|
||||
'', '', self._anon_tx_ring_size, 1, False,
|
||||
{'conf_target': self._conf_target}]
|
||||
return self.rpc_callback('sendtypeto', params)
|
||||
|
||||
def getScriptForPubkeyHash(self, pkh):
|
||||
return CScript([OP_DUP, OP_HASH160, pkh, OP_EQUALVERIFY, OP_CHECKSIG])
|
||||
|
||||
|
||||
class PARTInterfaceBlind(PARTInterface):
|
||||
@staticmethod
|
||||
def balance_type():
|
||||
return BalanceTypes.BLIND
|
||||
|
||||
|
||||
class PARTInterfaceAnon(PARTInterface):
|
||||
@staticmethod
|
||||
def balance_type():
|
||||
return BalanceTypes.ANON
|
||||
|
||||
|
@ -30,6 +30,7 @@ def js_error(self, error_str):
|
||||
|
||||
|
||||
def js_wallets(self, url_split, post_string, is_json):
|
||||
# TODO: Withdrawals
|
||||
return bytes(json.dumps(self.server.swap_client.getWalletsInfo()), 'UTF-8')
|
||||
|
||||
|
||||
|
@ -18,11 +18,35 @@
|
||||
{% else %}
|
||||
<table>
|
||||
<tr><td>Balance:</td><td>{{ w.balance }}</td>{% if w.unconfirmed %}<td>Unconfirmed:</td><td>{{ w.unconfirmed }}</td>{% endif %}</tr>
|
||||
|
||||
|
||||
{% if w.cid == '1' %}
|
||||
<tr><td>Blind Balance:</td><td>{{ w.blind_balance }}</td>{% if w.blind_unconfirmed %}<td>Blind Unconfirmed:</td><td>{{ w.blind_unconfirmed }}</td>{% endif %}</tr>
|
||||
<tr><td>Anon Balance:</td><td>{{ w.anon_balance }}</td>{% if w.anon_unconfirmed %}<td>Anon Unconfirmed:</td><td>{{ w.anon_unconfirmed }}</td>{% endif %}</tr>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<tr><td>Blocks:</td><td>{{ w.blocks }}</td></tr>
|
||||
<tr><td>Synced:</td><td>{{ w.synced }}</td></tr>
|
||||
<tr><td>Expected Seed:</td><td>{{ w.expected_seed }}</td>{% if w.expected_seed != true %}<td><input type="submit" name="reseed_{{ w.cid }}" value="Reseed wallet" onclick="confirmReseed()"></td>{% endif %}</tr>
|
||||
{% if w.cid == '1' %}
|
||||
<tr><td>Stealth Address</td><td colspan=2>{{ w.stealth_address }}</td></tr>
|
||||
{% endif %}
|
||||
<tr><td><input type="submit" name="newaddr_{{ w.cid }}" value="Deposit Address"></td><td colspan=2>{{ w.deposit_address }}</td></tr>
|
||||
<tr><td><input type="submit" name="withdraw_{{ w.cid }}" value="Withdraw"></td><td>Amount: <input type="text" name="amt_{{ w.cid }}"></td><td>Address: <input type="text" name="to_{{ w.cid }}"></td><td>Subtract fee: <input type="checkbox" name="subfee_{{ w.cid }}"></td></tr>
|
||||
<tr><td><input type="submit" name="withdraw_{{ w.cid }}" value="Withdraw"></td><td>Amount: <input type="text" name="amt_{{ w.cid }}" value="{{ w.wd_value }}"></td><td>Address: <input type="text" name="to_{{ w.cid }}" value="{{ w.wd_address }}"></td><td>Subtract fee: <input type="checkbox" name="subfee_{{ w.cid }}" {% if w.wd_subfee==true %} checked="true"{% endif %}></td></tr>
|
||||
{% if w.cid == '1' %}
|
||||
<tr><td>Type From, To</td><td>
|
||||
<select name="withdraw_type_from_{{ w.cid }}">
|
||||
<option value="plain"{% if w.wd_type_from == 'plain' %} selected{% endif %}>Plain</option>
|
||||
<option value="blind"{% if w.wd_type_from == 'blind' %} selected{% endif %}>Blind</option>
|
||||
<option value="anon"{% if w.wd_type_from == 'anon' %} selected{% endif %}>Anon</option>
|
||||
</select>
|
||||
<select name="withdraw_type_to_{{ w.cid }}">
|
||||
<option value="plain"{% if w.wd_type_to == 'plain' %} selected{% endif %}>Plain</option>
|
||||
<option value="blind"{% if w.wd_type_to == 'blind' %} selected{% endif %}>Blind</option>
|
||||
<option value="anon"{% if w.wd_type_to == 'anon' %} selected{% endif %}>Anon</option>
|
||||
</select></td></tr>
|
||||
{% endif %}
|
||||
<tr><td>Fee Rate:</td><td>{{ w.fee_rate }}</td><td>Est Fee:</td><td>{{ w.est_fee }}</td></tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
Loading…
Reference in New Issue
Block a user