mirror of
https://github.com/basicswap/basicswap.git
synced 2024-11-17 00:07:56 +00:00
api: getcoinseed shows seed id
This commit is contained in:
parent
c2d6cdafdd
commit
b6046fdbf3
13 changed files with 109 additions and 54 deletions
|
@ -1,3 +1,3 @@
|
|||
name = "basicswap"
|
||||
|
||||
__version__ = "0.11.58"
|
||||
__version__ = "0.11.59"
|
||||
|
|
|
@ -4273,7 +4273,7 @@ class BasicSwap(BaseApp):
|
|||
except AutomationConstraint as e:
|
||||
self.log.info('Not auto accepting bid {}, {}'.format(bid.bid_id.hex(), str(e)))
|
||||
if self.debug:
|
||||
self.logEvent(Concepts.AUTOMATION,
|
||||
self.logEvent(Concepts.BID,
|
||||
bid.bid_id,
|
||||
EventLogTypes.AUTOMATION_CONSTRAINT,
|
||||
str(e),
|
||||
|
@ -5814,7 +5814,7 @@ class BasicSwap(BaseApp):
|
|||
session.remove()
|
||||
self.mxDB.release()
|
||||
|
||||
def updateWalletInfo(self, coin):
|
||||
def updateWalletInfo(self, coin) -> None:
|
||||
# Store wallet info to db so it's available after startup
|
||||
try:
|
||||
bi = self.getBlockchainInfo(coin)
|
||||
|
@ -6141,15 +6141,22 @@ class BasicSwap(BaseApp):
|
|||
session.remove()
|
||||
self.mxDB.release()
|
||||
|
||||
def getAutomationStrategy(self, strategy_id):
|
||||
self.mxDB.acquire()
|
||||
def getAutomationStrategy(self, strategy_id: int):
|
||||
try:
|
||||
session = scoped_session(self.session_factory)
|
||||
session = self.openSession()
|
||||
return session.query(AutomationStrategy).filter_by(record_id=strategy_id).first()
|
||||
finally:
|
||||
session.close()
|
||||
session.remove()
|
||||
self.mxDB.release()
|
||||
self.closeSession(session, commit=False)
|
||||
|
||||
def updateAutomationStrategy(self, strategy_id: int, data, note: str) -> None:
|
||||
try:
|
||||
session = self.openSession()
|
||||
strategy = session.query(AutomationStrategy).filter_by(record_id=strategy_id).first()
|
||||
strategy.data = json.dumps(data).encode('utf-8')
|
||||
strategy.note = note
|
||||
session.add(strategy)
|
||||
finally:
|
||||
self.closeSession(session)
|
||||
|
||||
def getLinkedStrategy(self, linked_type, linked_id):
|
||||
self.mxDB.acquire()
|
||||
|
@ -6211,7 +6218,7 @@ class BasicSwap(BaseApp):
|
|||
if session is None:
|
||||
self.closeSession(use_session)
|
||||
|
||||
def addSMSGAddress(self, pubkey_hex, addressnote=None):
|
||||
def addSMSGAddress(self, pubkey_hex: str, addressnote: str = None) -> None:
|
||||
self.mxDB.acquire()
|
||||
try:
|
||||
session = scoped_session(self.session_factory)
|
||||
|
@ -6229,7 +6236,7 @@ class BasicSwap(BaseApp):
|
|||
session.remove()
|
||||
self.mxDB.release()
|
||||
|
||||
def editSMSGAddress(self, address, active_ind, addressnote):
|
||||
def editSMSGAddress(self, address: str, active_ind: int, addressnote: str) -> None:
|
||||
self.mxDB.acquire()
|
||||
try:
|
||||
session = scoped_session(self.session_factory)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020-2022 tecnovert
|
||||
# Copyright (c) 2020-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
@ -260,7 +260,7 @@ class BTCInterface(CoinInterface):
|
|||
last_block_header = prev_block_header
|
||||
raise ValueError(f'Block header not found at time: {time}')
|
||||
|
||||
def initialiseWallet(self, key_bytes: bytes):
|
||||
def initialiseWallet(self, key_bytes: bytes) -> None:
|
||||
key_wif = self.encodeKey(key_bytes)
|
||||
|
||||
self.rpc_callback('sethdseed', [True, key_wif])
|
||||
|
@ -388,11 +388,11 @@ class BTCInterface(CoinInterface):
|
|||
def getPubkey(self, privkey):
|
||||
return PublicKey.from_secret(privkey).format()
|
||||
|
||||
def getAddressHashFromKey(self, key) -> bytes:
|
||||
def getAddressHashFromKey(self, key: bytes) -> bytes:
|
||||
pk = self.getPubkey(key)
|
||||
return hash160(pk)
|
||||
|
||||
def getSeedHash(self, seed):
|
||||
def getSeedHash(self, seed) -> bytes:
|
||||
return self.getAddressHashFromKey(seed)[::-1]
|
||||
|
||||
def verifyKey(self, k: bytes) -> bool:
|
||||
|
|
|
@ -163,7 +163,7 @@ class FIROInterface(BTCInterface):
|
|||
|
||||
return CScript([OP_HASH160, script_hash_hash, OP_EQUAL])
|
||||
|
||||
def getSeedHash(self, seed):
|
||||
def getSeedHash(self, seed) -> bytes:
|
||||
return hash160(seed)[::-1]
|
||||
|
||||
def encodeScriptDest(self, script):
|
||||
|
|
|
@ -127,7 +127,7 @@ class XMRInterface(CoinInterface):
|
|||
self.createWallet(params)
|
||||
self.openWallet(self._wallet_filename)
|
||||
|
||||
def ensureWalletExists(self):
|
||||
def ensureWalletExists(self) -> None:
|
||||
with self._mx_wallet:
|
||||
self.openWallet(self._wallet_filename)
|
||||
|
||||
|
@ -190,12 +190,12 @@ class XMRInterface(CoinInterface):
|
|||
def walletRestoreHeight(self):
|
||||
return self._restore_height
|
||||
|
||||
def getMainWalletAddress(self):
|
||||
def getMainWalletAddress(self) -> str:
|
||||
with self._mx_wallet:
|
||||
self.openWallet(self._wallet_filename)
|
||||
return self.rpc_wallet_cb('get_address')['address']
|
||||
|
||||
def getNewAddress(self, placeholder):
|
||||
def getNewAddress(self, placeholder) -> str:
|
||||
with self._mx_wallet:
|
||||
self.openWallet(self._wallet_filename)
|
||||
return self.rpc_wallet_cb('create_address', {'account_index': 0})['address']
|
||||
|
@ -204,19 +204,19 @@ class XMRInterface(CoinInterface):
|
|||
self._log.warning('TODO - estimate fee rate?')
|
||||
return 0.0, 'unused'
|
||||
|
||||
def getNewSecretKey(self):
|
||||
def getNewSecretKey(self) -> bytes:
|
||||
return edu.get_secret()
|
||||
|
||||
def pubkey(self, key):
|
||||
def pubkey(self, key: bytes) -> bytes:
|
||||
return edf.scalarmult_B(key)
|
||||
|
||||
def encodeKey(self, vk):
|
||||
def encodeKey(self, vk: bytes) -> str:
|
||||
return vk[::-1].hex()
|
||||
|
||||
def decodeKey(self, k_hex):
|
||||
def decodeKey(self, k_hex: str) -> bytes:
|
||||
return bytes.fromhex(k_hex)[::-1]
|
||||
|
||||
def encodePubkey(self, pk):
|
||||
def encodePubkey(self, pk: bytes) -> str:
|
||||
return edu.encodepoint(pk)
|
||||
|
||||
def decodePubkey(self, pke):
|
||||
|
@ -225,12 +225,12 @@ class XMRInterface(CoinInterface):
|
|||
def getPubkey(self, privkey):
|
||||
return ed25519_get_pubkey(privkey)
|
||||
|
||||
def getAddressFromKeys(self, key_view, key_spend):
|
||||
def getAddressFromKeys(self, key_view: bytes, key_spend: bytes) -> str:
|
||||
pk_view = self.getPubkey(key_view)
|
||||
pk_spend = self.getPubkey(key_spend)
|
||||
return xmr_util.encode_address(pk_view, pk_spend)
|
||||
|
||||
def verifyKey(self, k):
|
||||
def verifyKey(self, k: int) -> bool:
|
||||
i = b2i(k)
|
||||
return (i < edf.l and i > 8)
|
||||
|
||||
|
@ -239,23 +239,23 @@ class XMRInterface(CoinInterface):
|
|||
# Checks for small order
|
||||
return verify_ed25519_point(pubkey_bytes)
|
||||
|
||||
def proveDLEAG(self, key):
|
||||
def proveDLEAG(self, key: bytes) -> bytes:
|
||||
privkey = PrivateKey(key)
|
||||
return dleag_prove(privkey)
|
||||
|
||||
def verifyDLEAG(self, dleag_bytes):
|
||||
def verifyDLEAG(self, dleag_bytes: bytes) -> bool:
|
||||
return dleag_verify(dleag_bytes)
|
||||
|
||||
def lengthDLEAG(self):
|
||||
def lengthDLEAG(self) -> int:
|
||||
return dleag_proof_len()
|
||||
|
||||
def sumKeys(self, ka, kb):
|
||||
def sumKeys(self, ka: bytes, kb: bytes) -> bytes:
|
||||
return ed25519_scalar_add(ka, kb)
|
||||
|
||||
def sumPubkeys(self, Ka, Kb):
|
||||
def sumPubkeys(self, Ka: bytes, Kb: bytes) -> bytes:
|
||||
return ed25519_add(Ka, Kb)
|
||||
|
||||
def encodeSharedAddress(self, Kbv, Kbs):
|
||||
def encodeSharedAddress(self, Kbv: bytes, Kbs: bytes) -> str:
|
||||
return xmr_util.encode_address(Kbv, Kbs)
|
||||
|
||||
def publishBLockTx(self, kbv, Kbs, output_amount, feerate, delay_for: int = 10, unlock_time: int = 0) -> bytes:
|
||||
|
@ -494,14 +494,14 @@ class XMRInterface(CoinInterface):
|
|||
self._wallet_password = orig_password
|
||||
raise e
|
||||
|
||||
def unlockWallet(self, password):
|
||||
def unlockWallet(self, password: str) -> None:
|
||||
self._log.info('unlockWallet - {}'.format(self.ticker()))
|
||||
self._wallet_password = password
|
||||
|
||||
if not self._have_checked_seed:
|
||||
self._sc.checkWalletSeed(self.coin_type())
|
||||
|
||||
def lockWallet(self):
|
||||
def lockWallet(self) -> None:
|
||||
self._log.info('lockWallet - {}'.format(self.ticker()))
|
||||
self._wallet_password = None
|
||||
|
||||
|
|
|
@ -551,10 +551,17 @@ def js_getcoinseed(self, url_split, post_string, is_json) -> bytes:
|
|||
raise ValueError('Particl wallet seed is set from the Basicswap mnemonic.')
|
||||
|
||||
ci = swap_client.ci(coin)
|
||||
seed = swap_client.getWalletKey(coin, 1)
|
||||
if coin == Coins.XMR:
|
||||
key_view = swap_client.getWalletKey(coin, 1, for_ed25519=True)
|
||||
key_spend = swap_client.getWalletKey(coin, 2, for_ed25519=True)
|
||||
address = ci.getAddressFromKeys(key_view, key_spend)
|
||||
return bytes(json.dumps({'coin': ci.ticker(), 'key_view': ci.encodeKey(key_view), 'key_spend': ci.encodeKey(key_spend), 'address': address}), 'UTF-8')
|
||||
|
||||
seed_key = swap_client.getWalletKey(coin, 1)
|
||||
if coin == Coins.DASH:
|
||||
return bytes(json.dumps({'coin': ci.ticker(), 'seed': seed.hex(), 'mnemonic': ci.seedToMnemonic(seed)}), 'UTF-8')
|
||||
return bytes(json.dumps({'coin': ci.ticker(), 'seed': seed.hex()}), 'UTF-8')
|
||||
return bytes(json.dumps({'coin': ci.ticker(), 'seed': seed_key.hex(), 'mnemonic': ci.seedToMnemonic(seed_key)}), 'UTF-8')
|
||||
seed_id = ci.getSeedHash(seed_key)
|
||||
return bytes(json.dumps({'coin': ci.ticker(), 'seed': seed_key.hex(), 'seed_id': seed_id.hex()}), 'UTF-8')
|
||||
|
||||
|
||||
def js_setpassword(self, url_split, post_string, is_json) -> bytes:
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
<div class="pb-6 border-coolGray-100">
|
||||
<div class="flex flex-wrap items-center justify-between -m-2">
|
||||
<div class="w-full pt-2 text-center ">
|
||||
<form method="post" autocomplete="off">
|
||||
<div class="container px-0 mx-auto mt-5">
|
||||
<div class="overflow-x-auto relative border sm:rounded-lg">
|
||||
<table class="w-full text-sm text-left text-gray-500 outline-none border-gray-300">
|
||||
|
@ -69,11 +70,11 @@
|
|||
<tr class="bg-white border-t hover:bg-gray-50">
|
||||
<td class="py-4 px-6 bold w-96">Data</td>
|
||||
<td class="py-4 pr-5">
|
||||
<textarea class="outline-none block p-2.5 text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 w-full monospace" rows="5" readonly>{{ strategy.data }}</textarea>
|
||||
<textarea name="data" class="outline-none block p-2.5 text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 w-full monospace" rows="5" {% if not show_edit_form %}readonly{% endif %}>{{ strategy.data }}</textarea>
|
||||
<tr class="bg-white border-t hover:bg-gray-50">
|
||||
<td class="py-4 px-6 bold w-96">Notes</td>
|
||||
<td class="py-4 pr-5">
|
||||
<textarea class="outline-none block p-2.5 text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 w-full monospace" rows="5" readonly>{{ strategy.note }}</textarea>
|
||||
<textarea name="note" class="outline-none block p-2.5 text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 w-full monospace" rows="5" {% if not show_edit_form %}readonly{% endif %}>{{ strategy.note }}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -82,12 +83,27 @@
|
|||
<div class="p-6 pt-10 bg-white bg-opacity-60 rounded-b-md">
|
||||
<div class="w-full md:w-0/12">
|
||||
<div class="flex flex-wrap justify-end -m-1.5">
|
||||
{% if show_edit_form %}
|
||||
<div class="w-full md:w-auto p-1.5 ml-2">
|
||||
<button name="apply" value="Apply" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none"><svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round" ><polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline> <circle cx="12" cy="12" r="11"></circle></g></svg>Apply</button>
|
||||
</div>
|
||||
<div class="w-full md:w-auto p-1.5 ml-2">
|
||||
<button name="cancel" value="Cancel" type="submit"class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-red-500 hover:text-red-600 border border-red-400 hover:border-red-500 bg-white rounded-md shadow-button focus:ring-0 focus:outline-none"><svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ef5844" stroke-linejoin="round" ><line x1="16" y1="8" x2="8" y2="16" stroke="#ef5844"></line> <line x1="16" y1="16" x2="8" y2="8" stroke="#ef5844"></line> <circle cx="12" cy="12" r="11"></circle></g></svg>Cancel</button>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="w-full md:w-auto p-1.5">
|
||||
<button name="edit" value="edit" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none">
|
||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round" ><line x1="2" y1="23" x2="22" y2="23" stroke="#ffffff"></line> <line data-cap="butt" x1="13" y1="5" x2="17" y2="9"></line> <polygon points="8 18 3 19 4 14 16 2 20 6 8 18"></polygon></g></svg>Edit</button>
|
||||
</div>
|
||||
<div class="w-full md:w-auto p-1.5 ml-2">
|
||||
<a href="/automation" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md shadow-button focus:ring-0 focus:outline-non"><svg class="text-gray-500 w-5 h-5 mr-2" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="square" stroke-width="2" fill="none" stroke="#556987" stroke-linejoin="miter" class="nc-icon-wrapper" stroke-miterlimit="10"><line data-cap="butt" x1="18" y1="12" x2="7" y2="12" stroke-linecap="butt" stroke="#556987"></line> <polyline points=" 11,16 7,12 11,8 " stroke="#5569878"></polyline> <circle cx="12" cy="12" r="11"></circle></g></svg> <span>Back</span> </a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="formid" value="{{ form_id }}">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -241,7 +241,7 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tr class="bg-white border-t hover:bg-gray-50">
|
||||
<td class="py-4 px-6 bold w-96 bold">Debug Node</td>
|
||||
<td class="py-4 px-6 bold w-96 bold">Debug Mode</td>
|
||||
<td class="py-4 pr-5">
|
||||
<div class="w-52 md:flex-1">
|
||||
<div class="relative">
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2022 tecnovert
|
||||
# Copyright (c) 2022-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
import json
|
||||
|
||||
from .util import (
|
||||
PAGE_LIMIT,
|
||||
get_data_entry,
|
||||
get_data_entry_or,
|
||||
have_data_entry,
|
||||
set_pagination_filters,
|
||||
)
|
||||
|
@ -89,14 +92,29 @@ def page_automation_strategy(self, url_split, post_string):
|
|||
|
||||
messages = []
|
||||
err_messages = []
|
||||
form_data = self.checkForm(post_string, 'automation_strategy', err_messages)
|
||||
show_edit_form = False
|
||||
if form_data:
|
||||
if have_data_entry(form_data, 'edit'):
|
||||
show_edit_form = True
|
||||
if have_data_entry(form_data, 'apply'):
|
||||
try:
|
||||
data = json.loads(get_data_entry_or(form_data, 'data', ''))
|
||||
note = get_data_entry_or(form_data, 'note', '')
|
||||
swap_client.updateAutomationStrategy(strategy_id, data, note)
|
||||
messages.append('Updated')
|
||||
except Exception as e:
|
||||
err_messages.append(str(e))
|
||||
show_edit_form = True
|
||||
|
||||
strategy = swap_client.getAutomationStrategy(strategy_id)
|
||||
|
||||
formatted_strategy = {
|
||||
'label': strategy.label,
|
||||
'type': strConcepts(strategy.type_ind),
|
||||
'only_known_identities': 'True' if strategy.only_known_identities is True else 'False',
|
||||
'data': strategy.data,
|
||||
'note': strategy.note,
|
||||
'data': strategy.data.decode('utf-8'),
|
||||
'note': '' if not strategy.note else strategy.note,
|
||||
'created_at': strategy.created_at,
|
||||
}
|
||||
|
||||
|
@ -105,5 +123,6 @@ def page_automation_strategy(self, url_split, post_string):
|
|||
'messages': messages,
|
||||
'err_messages': err_messages,
|
||||
'strategy': formatted_strategy,
|
||||
'show_edit_form': show_edit_form,
|
||||
'summary': summary,
|
||||
})
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
- api: Can abandon bids.
|
||||
- If wallets are encrypted the system will only load in-progress bids when unlocked rather than at startup.
|
||||
- Can set overrides for automation strategies per identity.
|
||||
- ui: bids on expired offers won't show as available
|
||||
- ui: Bids on expired offers won't show as available.
|
||||
- api: getcoinseed shows seed id.
|
||||
- ui: Can edit automation strategy data.
|
||||
|
||||
|
||||
0.0.54
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2021-2022 tecnovert
|
||||
# Copyright (c) 2021-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
@ -260,6 +260,9 @@ class BasicSwapTest(BaseTest):
|
|||
self.callnoderpc('getnewaddress')
|
||||
assert self.swap_clients[0].checkWalletSeed(Coins.BTC) is True
|
||||
|
||||
rv = read_json_api(1800, 'getcoinseed', {'coin': 'XMR'})
|
||||
assert (rv['address'] == '47H7UDLzYEsR28BWttxp59SP1UVSxs4VKDJYSfmz7Wd4Fue5VWuoV9x9eejunwzVSmHWN37gBkaAPNf9VD4bTvwQKsBVWyK')
|
||||
|
||||
def do_test_01_full_swap(self, coin_from, coin_to):
|
||||
logging.info('---------- Test {} to {}'.format(coin_from.name, coin_to.name))
|
||||
|
||||
|
|
|
@ -132,6 +132,7 @@ class Test(BaseTest):
|
|||
|
||||
rv = read_json_api(1800, 'getcoinseed', {'coin': 'BTC'})
|
||||
assert (rv['seed'] == '8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b')
|
||||
assert (rv['seed_id'] == '3da5c0af91879e8ce97d9a843874601c08688078')
|
||||
|
||||
rv = read_json_api(1800, 'identities/ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F', {'set_label': 'test 1'})
|
||||
assert (len(rv) == 1)
|
||||
|
|
Loading…
Reference in a new issue