THORChain XMR swaps
See:ffe488ff,ff35b01cEnabled for test suite only pending activation on THORChain mainnet. Swapping to and from ETH and ERC20 tokens is currently untested. Sample LTC-to-XMR swap workflow (assumes --autosign): # Create the registration transaction (pass 1) (amount is optional): $ mmgen-swaptxcreate --memoless LTC 5.4321 XMR # Autosign the registration transaction and send it: $ mmgen-txsend => TxID # Get the reference number from the THORChain network: $ mmgen-remote --coin=rune get_refnum TxID => REFNUM # Create the swap transaction (pass 2) (amount is optional): $ mmgen-swaptxcreate --refnum=REFNUM LTC 5.4321 XMR # Sign and send the swap transaction: $ mmgen-txsend # Monitor your XMR wallet for the funds: $ mmgen-tool --coin=xmr twview Sample XMR-to-LTC swap workflow (assumes --autosign): # Create the registration transaction (pass 1) (amount is required): $ mmgen-swaptxcreate --memoless XMR 1.2345 LTC # Sign and send registration TX and get reference number as shown above # Create the swap transaction (pass 2) (amount is required): $ mmgen-swaptxcreate --refnum=REFNUM XMR 1.2345 LTC # Sign and send the swap transaction as shown above # Monitor your LTC wallet for the funds: $ mmgen-tool --coin=ltc twview Testing/demo: $ test/cmdtest.py --coin=ltc -e xmrswap For more information and examples, invoke `mmgen-swaptxcreate --help` More complete documentation will be provided at a later date.
This commit is contained in:
parent
a5e3a1807c
commit
ea9c2d296e
26 changed files with 556 additions and 19 deletions
|
|
@ -1 +1 @@
|
|||
16.3.0dev18
|
||||
16.3.0dev19
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ forks, types ‘B’, ‘S’ and ‘C’ (see ADDRESS TYPES below) are searched
|
|||
order for unused addresses. Note that sending to an unused address may be
|
||||
undesirable for Ethereum, where address (i.e. account) reuse is the norm. In
|
||||
that case, the user should specify a destination address on the command line.
|
||||
Monero tracking wallets are likely to contain no unused addresses in the
|
||||
desired destination account, or even in the entire wallet, in which case the
|
||||
user must create a new address via ‘mmgen-tool --coin=xmr listaddresses
|
||||
interactive=1’.
|
||||
|
||||
If the wallet contains eligible unused addresses with multiple Seed IDs, the
|
||||
user will be presented with a list of the lowest-indexed addresses of
|
||||
|
|
@ -52,8 +56,10 @@ preferred type for each Seed ID and prompted to choose from among them.
|
|||
|
||||
Change and destination addresses may also be specified manually with the
|
||||
CHG_ADDR and DEST_ADDR arguments. These are given either as full MMGen IDs
|
||||
or in the form [SEED_ID:]ADDRTYPE_CODE, with the following exception: for
|
||||
Ethereum the CHG_ADDR argument is not supported. See EXAMPLES below and the
|
||||
or in the form [SEED_ID:]ADDRTYPE_CODE, with the following exceptions: for
|
||||
Ethereum and Monero the CHG_ADDR argument is not supported, and for Monero
|
||||
the DEST_ADDR argument, if given, is replaced by an extended MMGen ID or a
|
||||
specifier in the form WALLET_NUM:ACCT_IDX. See EXAMPLES below and the
|
||||
‘mmgen-txcreate’ help screen for details.
|
||||
|
||||
While discouraged, sending change or swapping to non-wallet addresses is also
|
||||
|
|
|
|||
|
|
@ -98,4 +98,46 @@ EXAMPLES:
|
|||
Same as above, but proxy requests via the I2P router running on host gw1:
|
||||
|
||||
$ https_proxy=http://gw1:4444 {gc.prog_name} --proxy=env RUNE 1000 BTC
|
||||
|
||||
|
||||
MEMOLESS SWAP EXAMPLES:
|
||||
|
||||
The following examples assume --autosign
|
||||
|
||||
Initiate a BTC-to-XMR swap with autoselected destination address. The
|
||||
command produces a THORChain registration transaction:
|
||||
|
||||
$ {gc.prog_name} --memoless BTC 0.1234 XMR
|
||||
|
||||
Send the registration transaction:
|
||||
|
||||
$ mmgen-txsend
|
||||
=> TxID
|
||||
|
||||
Get the reference number from the THORChain network:
|
||||
|
||||
$ mmgen-remote --coin=rune get_refnum TxID
|
||||
|
||||
Create a BTC-to-XMR swap transaction using the reference number:
|
||||
|
||||
$ {gc.prog_name} --refnum=REFNUM BTC 0.1234 XMR
|
||||
|
||||
Send the swap transaction:
|
||||
|
||||
$ mmgen-txsend
|
||||
|
||||
Monitor your XMR wallet for the funds:
|
||||
|
||||
$ mmgen-tool --coin=xmr twview
|
||||
|
||||
Initiate a BTC-to-XMR swap with destination argument in the form
|
||||
WALLET_NUM:ACCT_IDX:
|
||||
|
||||
$ {gc.prog_name} --memoless BTC 0.1234 XMR 3:12
|
||||
|
||||
Initiate a BTC-to-XMR swap with destination argument being a specific
|
||||
address denoted by an extended MMGen ID in the form SEED_ID:ADDR_TYPE:
|
||||
WALLET_NUM/ACCT_IDX/ADDR_IDX:
|
||||
|
||||
$ {gc.prog_name} --memoless BTC 0.1234 XMR 4BA5D19B:M:3/12/7
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -84,10 +84,14 @@ opts_data = {
|
|||
+ the reference request TX (activates second pass).
|
||||
-s -N, --no-refreq-tx With --memoless, do not create a reference request TX.
|
||||
+ Instead, display the reference memo and exit.
|
||||
m- -p, --priority=N Specify an integer priority ‘N’ for inclusion of trans-
|
||||
mt -p, --priority=N Specify an integer priority ‘N’ for inclusion of trans-
|
||||
+ action in blockchain (higher number means higher fee).
|
||||
+ Valid parameters: {tp}.
|
||||
+ If option is omitted, the default priority will be used
|
||||
-s -p, --priority=N Specify an integer priority ‘N’ for inclusion of trans-
|
||||
+ action in blockchain (higher number means higher fee).
|
||||
+ XMR only. Valid params: {tp}
|
||||
+ If option is omitted, the default priority will be used
|
||||
-- -q, --quiet Suppress warnings; overwrite files without prompting
|
||||
-s -Q, --quote Get a swap quote and exit. Do not create transaction
|
||||
-s -r, --stream-interval=N Set block interval for streaming swap (default: {si})
|
||||
|
|
|
|||
25
mmgen/proto/xmr/addrdata.py
Normal file
25
mmgen/proto/xmr/addrdata.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# MMGen Wallet, a terminal-based cryptocurrency wallet
|
||||
# Copyright (C)2013-2026 The MMGen Project <mmgen@tuta.io>
|
||||
# Licensed under the GNU General Public License, Version 3:
|
||||
# https://www.gnu.org/licenses
|
||||
# Public project repositories:
|
||||
# https://github.com/mmgen/mmgen-wallet
|
||||
# https://gitlab.com/mmgen/mmgen-wallet
|
||||
|
||||
"""
|
||||
proto.xmr.addrdata: Monero AddrData and related classes
|
||||
"""
|
||||
|
||||
from ...base_obj import AsyncInit
|
||||
from ...addrdata import AddrData
|
||||
from ...tw.addresses import TwAddresses
|
||||
|
||||
class MoneroTwAddrData(AddrData, metaclass=AsyncInit):
|
||||
|
||||
async def __init__(self, cfg, proto, *, twctl=None):
|
||||
twaddrs = await TwAddresses(cfg, proto, add_twctl=False)
|
||||
rpc_data = await twaddrs.get_rpc_data()
|
||||
self.data = {k: v['addr'] for k, v in rpc_data.items()}
|
||||
|
||||
def mmaddr2coinaddr(self, mmaddr):
|
||||
return self.data.get(mmaddr)
|
||||
|
|
@ -31,6 +31,7 @@ class mainnet(CoinProtocol.RPC, CoinProtocol.DummyWIF, CoinProtocol.Base):
|
|||
addr_ver_info = {'12': 'monero', '2a': 'monero_sub', '13': 'monero_integrated'}
|
||||
pubkey_types = ('monero',)
|
||||
mmtypes = ('M',)
|
||||
preferred_mmtypes = ('M',)
|
||||
dfl_mmtype = 'M'
|
||||
pubkey_type = 'monero' # required by DummyWIF
|
||||
avg_bdi = 120
|
||||
|
|
@ -39,6 +40,7 @@ class mainnet(CoinProtocol.RPC, CoinProtocol.DummyWIF, CoinProtocol.Base):
|
|||
coin_amt = 'XMRAmt'
|
||||
sign_mode = 'standalone'
|
||||
has_usr_fee = False
|
||||
address_reuse_ok = False
|
||||
|
||||
coin_cfg_opts = (
|
||||
'ignore_daemon_version',
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ class MoneroTwAddresses(MoneroTwView, TwAddresses):
|
|||
|
||||
include_empty = True
|
||||
has_used = True
|
||||
autochg_ignore_labels = True
|
||||
autochg_match_full_list = True
|
||||
prompt_fs_repl = {'XMR': (
|
||||
(1, 'Filters: show [E]mpty addrs, [u]sed addrs, all [L]abels'),
|
||||
(3, 'Actions: [q]uit menu, add [l]abel, [N]ew acct, [n]ew addr, [R]efresh bals:'))}
|
||||
|
|
@ -50,6 +52,23 @@ class MoneroTwAddresses(MoneroTwView, TwAddresses):
|
|||
removed_key_mappings = {
|
||||
'D': 'i_addr_delete'}
|
||||
|
||||
def get_target(self, key_in):
|
||||
from ....addr import AddrIdx, MoneroIdx
|
||||
return '{}:{}'.format(
|
||||
self.al_id,
|
||||
'{:0{w1}}:{:0{w2}}'.format(
|
||||
*map(int, key_in.split(':')),
|
||||
w1 = AddrIdx.max_digits,
|
||||
w2 = MoneroIdx.max_digits))
|
||||
|
||||
@staticmethod
|
||||
def get_bisect_key(d):
|
||||
return d.twmmid.addr.sort_key
|
||||
|
||||
@staticmethod
|
||||
def get_match_key(d):
|
||||
return d.twmmid.addr.acct_sort_key
|
||||
|
||||
class display_type:
|
||||
|
||||
class squeezed(MoneroTwView.display_type.squeezed):
|
||||
|
|
|
|||
|
|
@ -10,7 +10,10 @@
|
|||
proto.xmr.tw.ctl: Monero tracking wallet control class
|
||||
"""
|
||||
|
||||
from ....tw.ctl import TwCtl, write_mode
|
||||
from ....addr import CoinAddr
|
||||
from ....tw.shared import TwLabel
|
||||
from ....tw.ctl import TwCtl, write_mode, label_addr_pair
|
||||
from ....tw.addresses import TwAddresses
|
||||
|
||||
class MoneroTwCtl(TwCtl):
|
||||
|
||||
|
|
@ -46,3 +49,11 @@ class MoneroTwCtl(TwCtl):
|
|||
compat_call = True)
|
||||
op.c.call('close_wallet')
|
||||
return await op.main(add_timestr=add_timestr)
|
||||
|
||||
async def get_label_addr_pairs(self):
|
||||
twaddrs = await TwAddresses(self.cfg, self.proto, add_twctl=False)
|
||||
rpc_data = await twaddrs.get_rpc_data()
|
||||
return [label_addr_pair(
|
||||
TwLabel(self.proto, k),
|
||||
CoinAddr(self.proto, v['addr'])
|
||||
) for k, v in rpc_data.items()]
|
||||
|
|
|
|||
|
|
@ -43,9 +43,10 @@ class MoneroTwView:
|
|||
'twmmid': lambda i: i.twmmid.sort_key} # sort_key begins with acct_sort_key
|
||||
|
||||
class MoneroTwViewItem(TwUnspentOutputs.MMGenTwUnspentOutput):
|
||||
valid_attrs = {'amt', 'unlocked_amt', 'comment', 'twmmid', 'addr', 'confs', 'is_used', 'skip'}
|
||||
valid_attrs = {'amt', 'unlocked_amt', 'comment', 'twmmid', 'al_id', 'addr', 'confs', 'is_used', 'skip'}
|
||||
unlocked_amt = ImmutableAttr(CoinAmtChk, include_proto=True)
|
||||
is_used = ImmutableAttr(bool)
|
||||
al_id = ImmutableAttr(str)
|
||||
|
||||
class rpc:
|
||||
caps = ()
|
||||
|
|
@ -60,6 +61,7 @@ class MoneroTwView:
|
|||
|
||||
if dump_data:
|
||||
self.sid = SeedID(sid=dump_data[0]['seed_id'])
|
||||
self.al_id = self.sid + ':M'
|
||||
|
||||
self.total = self.unlocked_total = self.proto.coin_amt('0')
|
||||
|
||||
|
|
@ -112,6 +114,7 @@ class MoneroTwView:
|
|||
self.MoneroTwViewItem(
|
||||
self.proto,
|
||||
twmmid = twmmid,
|
||||
al_id = twmmid.addr.al_id,
|
||||
addr = data['addr'],
|
||||
confs = data['confs'],
|
||||
is_used = data['is_used'],
|
||||
|
|
|
|||
|
|
@ -13,3 +13,7 @@ proto.xmr.tx.base: Monero base transaction class
|
|||
class Base:
|
||||
is_compat = True
|
||||
has_comment = False
|
||||
|
||||
@property
|
||||
def nondata_outputs(self):
|
||||
return ()
|
||||
|
|
|
|||
|
|
@ -27,6 +27,12 @@ class New(Base, TxNew):
|
|||
async def set_gas(self, *, to_addr=None, force=False):
|
||||
pass
|
||||
|
||||
def process_data_output_arg(self, arg):
|
||||
pass
|
||||
|
||||
def get_addrdata_from_files(self, proto, addrfiles):
|
||||
pass
|
||||
|
||||
async def get_funds_remaining(self, fee, outputs_sum, start_fee_desc):
|
||||
return True
|
||||
|
||||
|
|
|
|||
18
mmgen/proto/xmr/tx/new_swap.py
Normal file
18
mmgen/proto/xmr/tx/new_swap.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# MMGen Wallet, a terminal-based cryptocurrency wallet
|
||||
# Copyright (C)2013-2026 The MMGen Project <mmgen@tuta.io>
|
||||
# Licensed under the GNU General Public License, Version 3:
|
||||
# https://www.gnu.org/licenses
|
||||
# Public project repositories:
|
||||
# https://github.com/mmgen/mmgen-wallet
|
||||
# https://gitlab.com/mmgen/mmgen-wallet
|
||||
|
||||
"""
|
||||
proto.xmr.tx.new_swap: Monero new swap transaction class
|
||||
"""
|
||||
|
||||
from ....tx.new_swap import NewSwap as TxNewSwap
|
||||
|
||||
from .new import New
|
||||
|
||||
class NewSwap(New, TxNewSwap):
|
||||
desc = 'Monero swap transaction'
|
||||
|
|
@ -99,9 +99,9 @@ class TwAddresses(TwView):
|
|||
def coinaddr_list(self):
|
||||
return [d.addr for d in self.data]
|
||||
|
||||
async def __init__(self, cfg, proto, *, minconf=1, mmgen_addrs='', get_data=False):
|
||||
async def __init__(self, cfg, proto, *, minconf=1, mmgen_addrs='', get_data=False, add_twctl=True):
|
||||
|
||||
await super().__init__(cfg, proto)
|
||||
await super().__init__(cfg, proto, add_twctl=add_twctl)
|
||||
|
||||
self.minconf = NonNegativeInt(minconf)
|
||||
self.spc_w = 5 + self.has_age + self.has_used # 1 space between cols + 1 leading space in fs
|
||||
|
|
|
|||
|
|
@ -195,12 +195,12 @@ class TwView(MMGenObject, metaclass=AsyncInit):
|
|||
def __new__(cls, cfg, proto, *args, **kwargs):
|
||||
return MMGenObject.__new__(proto.base_proto_subclass(cls, cls.mod_subpath))
|
||||
|
||||
async def __init__(self, cfg, proto):
|
||||
async def __init__(self, cfg, proto, *, add_twctl=True):
|
||||
self.cfg = cfg
|
||||
self.proto = proto
|
||||
if have_rpc := 'rpc_init' in proto.mmcaps:
|
||||
self.rpc = await rpc_init(cfg, proto)
|
||||
if self.has_twctl:
|
||||
if self.has_twctl and add_twctl:
|
||||
from .ctl import TwCtl
|
||||
self.twctl = await TwCtl(cfg, proto, mode='w', no_rpc=not have_rpc)
|
||||
self.amt_iwidth_keys = {'amt': 'iwidth'} | ({'amt2': 'iwidth2'} if self.has_amt2 else {})
|
||||
|
|
|
|||
|
|
@ -220,6 +220,9 @@ class New(Base):
|
|||
elif arg is None:
|
||||
res = al.get_change_address_by_addrtype(None, exclude=exclude, desc=desc)
|
||||
req_desc = 'of any allowed address type'
|
||||
elif al.is_account_based: # arg is an acct_id
|
||||
res = al.get_change_address(arg, exclude=exclude, desc=desc)
|
||||
req_desc = f'matching account {al.al_id}:{arg}'
|
||||
elif obj := get_obj(MMGenAddrType, proto=proto, id_str=arg, silent=True):
|
||||
res = al.get_change_address_by_addrtype(obj, exclude=exclude, desc=desc)
|
||||
req_desc = f'of address type {arg!r}'
|
||||
|
|
|
|||
|
|
@ -48,7 +48,11 @@ class NewSwap(BaseSwapMethods, New):
|
|||
self._non_wallet_addr_confirm(message)
|
||||
|
||||
async def get_swap_output(self, proto, arg, addrfiles, desc):
|
||||
if arg:
|
||||
|
||||
def is_acct_id(arg):
|
||||
return (ss := arg.split(':', 1)) and all(map(is_int, ss))
|
||||
|
||||
if arg and not (desc == 'destination' and is_acct_id(arg)):
|
||||
from ..addrdata import TwAddrData
|
||||
pa = self.parse_cmdline_arg(
|
||||
proto,
|
||||
|
|
@ -204,7 +208,8 @@ class NewSwap(BaseSwapMethods, New):
|
|||
from ..rpc import rpc_init
|
||||
if not args.send_amt:
|
||||
die(1, 'With --memoless (reference request transaction), you must supply a send amount')
|
||||
self.rpc = await rpc_init(self.cfg, self.proto)
|
||||
if 'rpc_init' in self.proto.mmcaps:
|
||||
self.rpc = await rpc_init(self.cfg, self.proto)
|
||||
qd = self.swap_proto_mod.quote_client(self, args.send_amt)
|
||||
await self.display_quote_loop(qd, deduct_est_fee=False)
|
||||
self.reference_memo = self.swap_proto_mod.reference_memo(
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ def op(op, cfg, infile, wallets, *, spec=None, compat_call=False):
|
|||
from ..cfg import Config
|
||||
cfg = Config({
|
||||
'_clone': cfg,
|
||||
'coin': 'XMR',
|
||||
'compat': True,
|
||||
'full_address': cfg.full_address or compat_call,
|
||||
'xmrwallet_compat': True} | ({} if cfg.offline else {
|
||||
|
|
|
|||
|
|
@ -582,6 +582,7 @@ class CmdTestAutosignThreaded(CmdTestAutosignBase):
|
|||
need_rbf = False,
|
||||
dump_hex = False,
|
||||
expect_pat = None,
|
||||
is_xmr = False,
|
||||
mark_sent = False):
|
||||
|
||||
if need_rbf and not self.proto.cap('rbf'):
|
||||
|
|
@ -604,6 +605,11 @@ class CmdTestAutosignThreaded(CmdTestAutosignBase):
|
|||
t.expect(expect_pat, regex=True)
|
||||
elif mark_sent:
|
||||
t.written_to_file('Sent automount transaction')
|
||||
elif is_xmr:
|
||||
if expect_pat:
|
||||
t.expect(expect_pat, regex=True)
|
||||
t.expect('Submit transaction? (y/N): ', 'y')
|
||||
t.written_to_file('Submitted transaction')
|
||||
else:
|
||||
t.view_tx('t', expect_pat=expect_pat)
|
||||
t.do_comment(comment)
|
||||
|
|
|
|||
|
|
@ -50,7 +50,19 @@ class ThornodeRPCServer(ThornodeServer):
|
|||
'reference': '13579',
|
||||
'asset': 'LTC.LTC',
|
||||
'memo': '=:c:qq6myf0qd6q5tln96ntl37hq0u7940w2xvs9jsuqv0:7967e4/3/0',
|
||||
'height': '12345678'}}
|
||||
'height': '12345678'},
|
||||
'fbbbd382': { # fbbbd382edd2d5478e0316b6c31ef6a0bbad57bcebc9d8b30cc52e5dbf107622
|
||||
'reference': '78787',
|
||||
'asset': 'XMR.XMR',
|
||||
'memo': '=:l:rltc1q6rs4znw8kajd6n6yn2snlfra3pluz3x5paj6x3:0/3/0',
|
||||
'height': '12349876'},
|
||||
'ae04ecd8': { # ae04ecd8ff1f0c13861bd2d6123ce33ea03a731ccd142f5ca2f2450a54f215ba
|
||||
'reference': '98765',
|
||||
'asset': 'LTC.LTC',
|
||||
'memo': '=:XMR.XMR:88u4waXXrPUD9EkCGMcFifKJakDZ6vx6zNpePuS238SLP7ziiMuqeP31c8ftJEDSymcSK88FFzKvQfoohF4LSyFu5E3yWTH:0/3/0',
|
||||
'height': '12346789'}}
|
||||
|
||||
refreq_txid_xmr = 'fbbbd382edd2d5478e0316b6c31ef6a0bbad57bcebc9d8b30cc52e5dbf107622'
|
||||
|
||||
inbounds_info = get_inbounds_info()
|
||||
|
||||
|
|
|
|||
|
|
@ -26,16 +26,19 @@ prices = {
|
|||
'LTC': 115,
|
||||
'BCH': 330,
|
||||
'ETH': 2304,
|
||||
'XMR': 550,
|
||||
'MM1': 0.998,
|
||||
'RUNE': 1.4}
|
||||
|
||||
gas_rate_units = {
|
||||
'BTC': 'satsperbyte',
|
||||
'ETH': 'gwei'}
|
||||
'ETH': 'gwei',
|
||||
'XMR': 'atomic'}
|
||||
|
||||
recommended_gas_rate = {
|
||||
'BTC': '6',
|
||||
'ETH': '1'}
|
||||
'ETH': '1',
|
||||
'XMR': '600'}
|
||||
|
||||
data_template_from_rune = {
|
||||
'outbound_delay_blocks': 0,
|
||||
|
|
|
|||
|
|
@ -51,12 +51,14 @@ cmd_groups_dfl = {
|
|||
'xmrwallet': gd('CmdTestXMRWallet', {}),
|
||||
'xmr_autosign': gd('CmdTestXMRAutosign', {}),
|
||||
'xmr_compat': gd('CmdTestXMRCompat', {'modname': 'xmr_autosign'}),
|
||||
'xmrswap': gd('CmdTestXMRSwap', {}),
|
||||
}
|
||||
|
||||
cmd_groups_extra = {
|
||||
'ethswap_eth': gd('CmdTestEthSwapEth', {'modname': 'ethswap'}),
|
||||
'ethbump_ltc': gd('CmdTestEthBumpLTC', {'modname': 'ethbump'}),
|
||||
'runeswap_rune': gd('CmdTestRuneSwapRune', {'modname': 'runeswap'}),
|
||||
'xmrswap_xmr': gd('CmdTestXMRSwapXMR', {'modname': 'xmrswap'}),
|
||||
'dev': gd('CmdTestDev', {'modname': 'misc'}),
|
||||
'regtest_legacy': gd('CmdTestRegtestBDBWallet', {'modname': 'regtest'}),
|
||||
'autosign_btc': gd('CmdTestAutosignBTC', {'modname': 'autosign'}),
|
||||
|
|
@ -263,6 +265,7 @@ cfgs = { # addr_idx_lists (except 31, 32, 33, 34) must contain exactly 8 address
|
|||
'57': {}, # runeswap
|
||||
'58': {}, # runeswap_rune
|
||||
'59': {}, # autosign_eth
|
||||
'77': {}, # xmrswap
|
||||
'99': {}, # dummy
|
||||
}
|
||||
|
||||
|
|
|
|||
362
test/cmdtest_d/xmrswap.py
Normal file
362
test/cmdtest_d/xmrswap.py
Normal file
|
|
@ -0,0 +1,362 @@
|
|||
# MMGen Wallet, a terminal-based cryptocurrency wallet
|
||||
# Copyright (C)2013-2026 The MMGen Project <mmgen@tuta.io>
|
||||
# Licensed under the GNU General Public License, Version 3:
|
||||
# https://www.gnu.org/licenses
|
||||
# Public project repositories:
|
||||
# https://github.com/mmgen/mmgen-wallet
|
||||
# https://gitlab.com/mmgen/mmgen-wallet
|
||||
|
||||
"""
|
||||
test.cmdtest_d.xmrswap: Monero swap tests for the cmdtest.py test suite
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
from .xmr_autosign import CmdTestXMRCompat
|
||||
from .swap import CmdTestSwap, CmdTestSwapMethods, create_cross_methods
|
||||
|
||||
class CmdTestXMRSwapMethods:
|
||||
|
||||
def _swaptxcreate_ui(
|
||||
self,
|
||||
t,
|
||||
prompt,
|
||||
*,
|
||||
tx_type = 'swap',
|
||||
inputs = '1',
|
||||
interactive_fee = None,
|
||||
file_desc = 'Unsigned transaction',
|
||||
tweaks = [],
|
||||
auto_chg_addr = None,
|
||||
auto_dest_addr = None,
|
||||
reload_quote = False,
|
||||
menu_prompt = None,
|
||||
expect_pats = []):
|
||||
if auto_chg_addr:
|
||||
t.expect(rf'Using.*{auto_chg_addr}.*as change address.*: ', 'y', regex=True)
|
||||
if tx_type == 'registration':
|
||||
if auto_dest_addr:
|
||||
t.expect(rf'Using.*{auto_dest_addr}.*as destination address.*: ', 'y', regex=True)
|
||||
t.expect('continue: ', '\n')
|
||||
t.expect(prompt, 'q')
|
||||
t.expect('spend from: ', f'{inputs}\n')
|
||||
elif tx_type in ('swap', 'xmr_swap'):
|
||||
t.expect(prompt, 'q')
|
||||
t.expect('to spend: ', f'{inputs}\n')
|
||||
t.expect('continue: ', '\n')
|
||||
if tx_type == 'xmr_swap':
|
||||
for pat in expect_pats:
|
||||
t.expect(pat, regex=True)
|
||||
t.expect('(y/N): ', 'y') # save?
|
||||
t.written_to_file('Unsigned transaction')
|
||||
return t
|
||||
t.expect('(Y/n): ', 'y') # fee OK?
|
||||
t.expect('(Y/n): ', 'y') # change OK?
|
||||
t.expect('(y/N): ', 'n') # add comment?
|
||||
t.expect('view: ', 't')
|
||||
for pat in expect_pats:
|
||||
t.expect(pat, regex=True)
|
||||
t.expect('to continue: ', '\n')
|
||||
t.expect('(y/N): ', 'y') # save?
|
||||
t.written_to_file('Unsigned automount transaction')
|
||||
return t
|
||||
|
||||
def _swaptxcreate_refreq(
|
||||
self,
|
||||
*,
|
||||
args,
|
||||
inputs,
|
||||
auto_chg_addr = None,
|
||||
auto_dest_addr = None,
|
||||
expect_pats = None):
|
||||
return self._user_txcreate(
|
||||
'bob',
|
||||
progname = 'swaptxcreate',
|
||||
opts = ['--monero-wallet-rpc-password=abc', '--memoless'],
|
||||
ui_handler = self._swaptxcreate_ui,
|
||||
ui_handler_args = {
|
||||
'prompt': self.rune_menu_prompt,
|
||||
'tx_type': 'registration',
|
||||
'inputs': inputs,
|
||||
'auto_chg_addr': auto_chg_addr,
|
||||
'auto_dest_addr': auto_dest_addr,
|
||||
'expect_pats': expect_pats},
|
||||
output_args = args)
|
||||
|
||||
def _swaptxcreate_refnum(
|
||||
self,
|
||||
*,
|
||||
args,
|
||||
inputs,
|
||||
tx_type = 'swap',
|
||||
add_opts = [],
|
||||
auto_chg_addr = None,
|
||||
auto_dest_addr = None,
|
||||
prompt = None,
|
||||
expect_pats = None):
|
||||
data = json.loads(self.read_from_tmpfile('memo_info.json'))
|
||||
return self._user_txcreate(
|
||||
'bob',
|
||||
progname = 'swaptxcreate',
|
||||
opts = ['--monero-wallet-rpc-password=abc', f'--refnum={data["reference"]}'] + add_opts,
|
||||
ui_handler = self._swaptxcreate_ui,
|
||||
ui_handler_args = {
|
||||
'prompt': prompt or self.menu_prompt,
|
||||
'tx_type': tx_type,
|
||||
'inputs': inputs,
|
||||
'auto_chg_addr': auto_chg_addr,
|
||||
'auto_dest_addr': auto_dest_addr,
|
||||
'expect_pats': expect_pats},
|
||||
output_args = args)
|
||||
|
||||
def _swaptxsend_refnum(self, expect_pat, *, add_opts=[], is_xmr=False):
|
||||
return self._user_txsend(
|
||||
'bob',
|
||||
add_opts = ['--monero-wallet-rpc-password=abc'] + add_opts,
|
||||
expect_pat = expect_pat,
|
||||
is_xmr = is_xmr,
|
||||
need_rbf = True)
|
||||
|
||||
class CmdTestXMRSwap(CmdTestXMRSwapMethods, CmdTestSwap):
|
||||
'Monero swap operations'
|
||||
|
||||
bdb_wallet = True
|
||||
tmpdir_nums = [77]
|
||||
networks = ('ltc',)
|
||||
thornode_servers = ('rpc', 'swap')
|
||||
cross_group = 'xmrswap_xmr'
|
||||
cross_coin = 'xmr'
|
||||
refreq_txid = 'ae04ecd8ff1f0c13861bd2d6123ce33ea03a731ccd142f5ca2f2450a54f215ba'
|
||||
refreq_txid_xmr = 'fbbbd382edd2d5478e0316b6c31ef6a0bbad57bcebc9d8b30cc52e5dbf107622'
|
||||
xmr_prompt = 'efresh balances:\b'
|
||||
|
||||
cmd_group_in = (
|
||||
('setup', 'regtest (Bob and Alice) mode setup'),
|
||||
('subgroup.ltc_setup', []),
|
||||
('subgroup.xmr_setup', []),
|
||||
('subgroup.swap', ['ltc_setup', 'xmr_setup']),
|
||||
('subgroup.xmr_swap', ['swap']),
|
||||
('xmr_wait_loop_kill', 'stopping autosign wait loop'),
|
||||
('xmr_stop_daemons', 'stopping the XMR daemons'))
|
||||
|
||||
cmd_subgroups = {
|
||||
'ltc_setup': (
|
||||
'creating Bob’s MMGen wallet and tracking wallet',
|
||||
('walletconv_bob', 'wallet creation (Bob)'),
|
||||
('addrgen_bob', 'address generation (Bob)'),
|
||||
('addrimport_bob', 'importing Bob’s addresses'),
|
||||
('bob_import_miner_addr', 'importing miner’s coinbase addr into Bob’s wallet'),
|
||||
('fund_bob1', 'funding Bob’s wallet'),
|
||||
('fund_bob2', 'funding Bob’s wallet'),
|
||||
('fund_bob3', 'funding Bob’s wallet'),
|
||||
('generate_ltc', 'mining a block'),
|
||||
('bob_bal1', 'Bob’s balance'),
|
||||
),
|
||||
'xmr_setup': (
|
||||
'setting miner’s and user’s XMR tracking wallets',
|
||||
('xmr_autosign_setup', ''),
|
||||
('xmr_autosign_xmr_setup', ''),
|
||||
('xmr_addrimport_user', ''),
|
||||
('xmr_gen_kafile_miner', ''),
|
||||
('xmr_gen_vkafile_user', ''),
|
||||
('xmr_create_wallet_miner', ''),
|
||||
('xmr_mine_initial_coins', ''),
|
||||
('xmr_fund_user1', ''),
|
||||
('xmr_mine_blocks_10', ''),
|
||||
('xmr_new_address_user1', ''),
|
||||
('xmr_new_address_user2', ''),
|
||||
('xmr_new_account_user', ''),
|
||||
('xmr_mine_blocks_10', ''),
|
||||
('xmr_user_listaddresses_refresh', ''),
|
||||
('xmr_wait_loop_start_compat', ''),
|
||||
),
|
||||
'swap': (
|
||||
'swap operations (LTC -> XMR)',
|
||||
('rune_addrgen', 'generating RUNE addresses'),
|
||||
('rune_addrimport', 'importing RUNE addresses'),
|
||||
('rune_bal_refresh', 'refreshing balances in RUNE tracking wallet'),
|
||||
('remote_get_refnum', 'getting the reference number'),
|
||||
('swaptxcreate_refreq1', 'creating an LTC->XMR swap transaction (refreq, auto chg, auto dest)'),
|
||||
('swaptxcreate_abort1', 'aborting the transaction'),
|
||||
('swaptxcreate_refreq2', 'creating an LTC->XMR swap transaction (refreq, auto chg, 1:0)'),
|
||||
('swaptxcreate_abort2', 'aborting the transaction'),
|
||||
('swaptxcreate_refreq3', 'creating an LTC->XMR swap transaction (refreq, auto chg, mmid dest)'),
|
||||
('swaptxsend_refreq1', 'sending the transaction'),
|
||||
('swaptxcreate_refreq4', 'creating an LTC->XMR swap transaction (refreq, auto chg, 1:1)'),
|
||||
('swaptxsend_refreq2', 'sending the transaction'),
|
||||
('swaptxcreate_refnum1', 'creating an LTC->XMR swap transaction (swap, auto chg, auto dest)'),
|
||||
('swaptxsend_refnum1', 'sending the swap transaction'),
|
||||
('generate_ltc', 'generating a block'),
|
||||
('swaptxcreate_refnum2', 'creating an LTC->XMR swap transaction (swap, no chg, auto dest)'),
|
||||
('swaptxsend_refnum2', 'sending the swap transaction'),
|
||||
('generate_ltc', 'generating a block'),
|
||||
('bob_bal2', 'Bob’s balance')),
|
||||
'xmr_swap': (
|
||||
'swap operations (XMR -> LTC)',
|
||||
('remote_get_refnum_xmr', 'getting the reference number'),
|
||||
('swaptxcreate_refreq7', 'creating an XMR->LTC swap transaction (refreq, auto chg, auto dest)'),
|
||||
('swaptxsend_refreq7', 'sending the transaction'),
|
||||
('swaptxcreate_refnum7', 'creating an XMR->LTC swap transaction (swap, auto chg, auto dest)'),
|
||||
('swaptxsend_refnum7', 'sending the transaction'),
|
||||
('xmr_mine_blocks_10', ''),
|
||||
('swaptxstatus_refnum7', 'getting the transaction status'))}
|
||||
|
||||
exec(create_cross_methods(cross_coin, cross_group, cmd_group_in, cmd_subgroups))
|
||||
|
||||
def __init__(self, cfg, trunner, cfgs, spawn):
|
||||
|
||||
super().__init__(cfg, trunner, cfgs, spawn)
|
||||
|
||||
self.spawn_env['MMGEN_TEST_SUITE_ENABLE_USER_PORT_SHIFT'] = '1'
|
||||
|
||||
if not trunner:
|
||||
return
|
||||
|
||||
globals()[self.cross_group] = self.create_cross_runner(trunner, add_cfg={})
|
||||
|
||||
def fund_bob1(self):
|
||||
return self.fund_wallet('bob', 500, mmtype='C')
|
||||
|
||||
def fund_bob2(self):
|
||||
return self.fund_wallet('bob', 50, mmtype='S')
|
||||
|
||||
def fund_bob3(self):
|
||||
return self.fund_wallet('bob', 25, mmtype='B')
|
||||
|
||||
def bob_bal1(self):
|
||||
return self._bob_bal(0, '575')
|
||||
|
||||
def swaptxcreate_refreq1(self):
|
||||
return self._swaptxcreate_refreq(
|
||||
args = ['LTC', '5.4321', 'XMR'],
|
||||
inputs = '3',
|
||||
auto_chg_addr = '98831F3A:B:2',
|
||||
auto_dest_addr = '98831F3A:M:1/0/1',
|
||||
expect_pats = ['88u4waXXrPUD9EkCGMcFif', r'to spend:.*\b0\b.*RUNE'])
|
||||
|
||||
def swaptxcreate_abort1(self):
|
||||
return self._txsend_abort()
|
||||
|
||||
def swaptxcreate_refreq2(self):
|
||||
return self._swaptxcreate_refreq(
|
||||
args = ['LTC', '5.4321', 'XMR', '1:0'],
|
||||
inputs = '3',
|
||||
auto_chg_addr = '98831F3A:B:2',
|
||||
auto_dest_addr = '98831F3A:M:1/0/1',
|
||||
expect_pats = ['88u4waXXrPUD9EkCGMcFif', r'to spend:.*\b0\b.*RUNE'])
|
||||
|
||||
def swaptxcreate_abort2(self):
|
||||
return self._txsend_abort()
|
||||
|
||||
def swaptxcreate_refreq3(self):
|
||||
return self._swaptxcreate_refreq(
|
||||
args = ['LTC', '5.4321', 'XMR', '98831F3A:M:1/0/1'],
|
||||
inputs = '3',
|
||||
auto_chg_addr = '98831F3A:B:2',
|
||||
expect_pats = ['88u4waXXrPUD9EkCGMcFif', r'to spend:.*\b0\b.*RUNE'])
|
||||
|
||||
def swaptxsend_refreq1(self):
|
||||
return self._user_txsend('bob', need_rbf=True)
|
||||
|
||||
def swaptxcreate_refreq4(self):
|
||||
return self._swaptxcreate_refreq(
|
||||
args = ['LTC', '5.4321', 'XMR', '1:1'],
|
||||
inputs = '3',
|
||||
auto_chg_addr = '98831F3A:B:2',
|
||||
auto_dest_addr = '98831F3A:M:1/1/0',
|
||||
expect_pats = ['89NVJJPWPw18P7XoqiYgj4', r'to spend:.*\b0\b.*RUNE'])
|
||||
|
||||
swaptxsend_refreq2 = swaptxsend_refreq1
|
||||
|
||||
def swaptxcreate_refnum1(self):
|
||||
return self._swaptxcreate_refnum(
|
||||
args = ['LTC', '5.4321', 'XMR'],
|
||||
inputs = '1',
|
||||
auto_chg_addr = '98831F3A:B:2',
|
||||
expect_pats = ['88u4waXXrPUD9EkCGMcFif', r'Spend amount:.*\b5\.43198765\b.*LTC'])
|
||||
|
||||
def swaptxsend_refnum1(self):
|
||||
return self._swaptxsend_refnum(r'Spend amount:.*\b5\.43198765\b.*LTC')
|
||||
|
||||
def swaptxcreate_refnum2(self):
|
||||
return self._swaptxcreate_refnum(
|
||||
args = ['LTC', 'XMR'],
|
||||
inputs = '2',
|
||||
expect_pats = ['88u4waXXrPUD9EkCGMcFif', r'Spend amount:.*24\.99998765'])
|
||||
|
||||
def swaptxsend_refnum2(self):
|
||||
return self._swaptxsend_refnum(r'Spend amount:.*24\.99998765')
|
||||
|
||||
def bob_bal2(self):
|
||||
return self._bob_bal(0, '544.56799927')
|
||||
|
||||
def remote_get_refnum_xmr(self):
|
||||
return self._remote_get_refnum(self.refreq_txid_xmr)
|
||||
|
||||
def swaptxcreate_refreq7(self):
|
||||
return self._swaptxcreate_refreq(
|
||||
args = ['XMR', '0.2345', 'LTC'],
|
||||
inputs = '3',
|
||||
auto_dest_addr = '98831F3A:B:3',
|
||||
expect_pats = ['rltc1q6rs4znw8k', r'to spend:.*\b0\b.*RUNE'])
|
||||
|
||||
def swaptxsend_refreq7(self):
|
||||
return self._user_txsend('bob', need_rbf=True)
|
||||
|
||||
def swaptxcreate_refnum7(self):
|
||||
return self._swaptxcreate_refnum(
|
||||
add_opts = ['--priority=3'],
|
||||
args = ['XMR', '0.2345', 'LTC'],
|
||||
inputs = '1',
|
||||
tx_type = 'xmr_swap',
|
||||
prompt = self.xmr_prompt,
|
||||
auto_dest_addr = '98831F3A:B:3',
|
||||
expect_pats = [r'Amount:.*0.234499978787', r'Priority:.*high'])
|
||||
|
||||
def swaptxsend_refnum7(self):
|
||||
return self._swaptxsend_refnum(r'Amount:.*0.234499978787', is_xmr=True)
|
||||
|
||||
def swaptxstatus_refnum7(self):
|
||||
return self._swaptxsend_refnum(r'Amount:.*0.234499978787', add_opts=['--status', '--verbose'])
|
||||
|
||||
class CmdTestXMRSwapXMR(CmdTestXMRSwapMethods, CmdTestSwapMethods, CmdTestXMRCompat):
|
||||
'Monero swap operations - Monero wallet'
|
||||
networks = ('xmr',)
|
||||
tmpdir_nums = [77]
|
||||
is_helper = True
|
||||
tx_relay_user = None
|
||||
user = 'bob'
|
||||
user_data = (
|
||||
# user sid autosign kal_range add_coind_args
|
||||
('miner', 'FE3C6545', False, '1', []),
|
||||
('bob', '98831F3A', True, '1-2', []))
|
||||
|
||||
cmd_group = CmdTestXMRCompat.cmd_group + (
|
||||
('user_txcreate_sweep1', 'creating a sweep transaction (address sweep)'),
|
||||
('new_address_user1', 'adding an address to user’s wallet (acct 0)'),
|
||||
('new_address_user2', 'adding an address to user’s wallet (acct 0)'),
|
||||
('new_account_user', 'adding an account to user’s wallet'),
|
||||
('user_listaddresses_refresh', 'listing the user’s wallet, with refresh'))
|
||||
|
||||
def user_txcreate_sweep1(self):
|
||||
return self._user_txops('txcreate', menu='s', sweep_menu='1', sweep_type='sweep')
|
||||
|
||||
def _new_address_user(self, wallet, acct, action):
|
||||
return self._new_addr_user_autosign(
|
||||
f'{wallet}:{acct}',
|
||||
action,
|
||||
rf'Creating new address for wallet .*{wallet}.*, account .*#{acct}.* with label '
|
||||
r'.*‘xmrwallet new address .*y/N\): ')
|
||||
|
||||
def new_address_user1(self):
|
||||
return self._new_address_user(1, 0, 'start')
|
||||
|
||||
def new_address_user2(self):
|
||||
return self._new_address_user(1, 0, 'continue')
|
||||
|
||||
def new_account_user(self):
|
||||
return self._new_addr_user_autosign(
|
||||
'1',
|
||||
'stop',
|
||||
r'Creating new account for wallet .*1.* with label '
|
||||
r'.*‘xmrwallet new account .*y/N\): ')
|
||||
|
|
@ -31,8 +31,7 @@ class overlay_fake_Daemon:
|
|||
'miner': 1,
|
||||
'bob': 2,
|
||||
'alice': 3}
|
||||
|
||||
if os.getenv('MMGEN_TEST_SUITE_ENABLE_USER_PORT_SHIFT'):
|
||||
if os.getenv('MMGEN_TEST_SUITE_ENABLE_USER_PORT_SHIFT') and self.proto.coin == 'XMR':
|
||||
return 1 << 7 | udata[self.test_user or self.cfg.test_user] << 5
|
||||
else:
|
||||
return 1 << 7
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ from .asset_orig import *
|
|||
class overlay_fake_THORChainSwapAsset:
|
||||
|
||||
assets_data = {
|
||||
'XMR': THORChainSwapAsset._ad('Monero', 'XMR', 'XMR.XMR', None, None, True),
|
||||
'ETH.MM1': THORChainSwapAsset._ad('MM1 Token (ETH)', None, 'ETH.MM1', None, 18, True),
|
||||
'ETH.JUNK': THORChainSwapAsset._ad('Junk Token (ETH)', None, 'ETH.JUNK', None, 6, True),
|
||||
'ETH.NONE': THORChainSwapAsset._ad('Banned Token (ETH)', None, 'ETH.NONE', None, 18, True)}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
[{"chain":"BCH","pub_key":"thorpub1addwnpepqvg02tp8umuqp36wy5ptpeqavkdu58gk0z8e7amnjyh3cpslfq9fqxhlmvp","address":"qpxmqf20pnzywzmjevclquekjzlvq5hx25s4ucj53r","halted":false,"global_trading_paused":false,"chain_trading_paused":false,"chain_lp_actions_paused":false,"observed_fee_rate":"2","gas_rate":"3","gas_rate_units":"satsperbyte","outbound_tx_size":"1500","outbound_fee":"74450","dust_threshold":"10000"},{"chain":"BTC","pub_key":"thorpub1addwnpepqvg02tp8umuqp36wy5ptpeqavkdu58gk0z8e7amnjyh3cpslfq9fqxhlmvp","address":"bc1qfkcz2ncvc3rskuktx8c8xd5shmq99ej45gq8wu","halted":false,"global_trading_paused":false,"chain_trading_paused":false,"chain_lp_actions_paused":false,"observed_fee_rate":"4","gas_rate":"6","gas_rate_units":"satsperbyte","outbound_tx_size":"1000","outbound_fee":"2120","dust_threshold":"1000"},{"chain":"ETH","pub_key":"thorpub1addwnpepqvg02tp8umuqp36wy5ptpeqavkdu58gk0z8e7amnjyh3cpslfq9fqxhlmvp","address":"0x41c88d3c0eda3f4df0bb4e5d0f4c81cc0232902c","router":"0xD37BbE5744D730a1d98d8DC97c42F0Ca46aD7146","halted":false,"global_trading_paused":false,"chain_trading_paused":false,"chain_lp_actions_paused":false,"observed_fee_rate":"10","gas_rate":"15","gas_rate_units":"gwei","outbound_tx_size":"100000","outbound_fee":"9190","dust_threshold":"1000"},{"chain":"LTC","pub_key":"thorpub1addwnpepqvg02tp8umuqp36wy5ptpeqavkdu58gk0z8e7amnjyh3cpslfq9fqxhlmvp","address":"rltc1qlvwym7fha5cuvs0c2vy2l86r7a8ayt8chwqsyr","halted":false,"global_trading_paused":false,"chain_trading_paused":false,"chain_lp_actions_paused":false,"observed_fee_rate":"74","gas_rate":"111","gas_rate_units":"satsperbyte","outbound_tx_size":"250","outbound_fee":"355075","dust_threshold":"100000"}]
|
||||
[{"chain":"BCH","pub_key":"thorpub1addwnpepqvg02tp8umuqp36wy5ptpeqavkdu58gk0z8e7amnjyh3cpslfq9fqxhlmvp","address":"qpxmqf20pnzywzmjevclquekjzlvq5hx25s4ucj53r","halted":false,"global_trading_paused":false,"chain_trading_paused":false,"chain_lp_actions_paused":false,"observed_fee_rate":"2","gas_rate":"3","gas_rate_units":"satsperbyte","outbound_tx_size":"1500","outbound_fee":"74450","dust_threshold":"10000"},{"chain":"BTC","pub_key":"thorpub1addwnpepqvg02tp8umuqp36wy5ptpeqavkdu58gk0z8e7amnjyh3cpslfq9fqxhlmvp","address":"bc1qfkcz2ncvc3rskuktx8c8xd5shmq99ej45gq8wu","halted":false,"global_trading_paused":false,"chain_trading_paused":false,"chain_lp_actions_paused":false,"observed_fee_rate":"4","gas_rate":"6","gas_rate_units":"satsperbyte","outbound_tx_size":"1000","outbound_fee":"2120","dust_threshold":"1000"},{"chain":"ETH","pub_key":"thorpub1addwnpepqvg02tp8umuqp36wy5ptpeqavkdu58gk0z8e7amnjyh3cpslfq9fqxhlmvp","address":"0x41c88d3c0eda3f4df0bb4e5d0f4c81cc0232902c","router":"0xD37BbE5744D730a1d98d8DC97c42F0Ca46aD7146","halted":false,"global_trading_paused":false,"chain_trading_paused":false,"chain_lp_actions_paused":false,"observed_fee_rate":"10","gas_rate":"15","gas_rate_units":"gwei","outbound_tx_size":"100000","outbound_fee":"9190","dust_threshold":"1000"},{"chain":"LTC","pub_key":"thorpub1addwnpepqvg02tp8umuqp36wy5ptpeqavkdu58gk0z8e7amnjyh3cpslfq9fqxhlmvp","address":"rltc1qlvwym7fha5cuvs0c2vy2l86r7a8ayt8chwqsyr","halted":false,"global_trading_paused":false,"chain_trading_paused":false,"chain_lp_actions_paused":false,"observed_fee_rate":"74","gas_rate":"111","gas_rate_units":"satsperbyte","outbound_tx_size":"250","outbound_fee":"355075","dust_threshold":"100000"},{"chain":"XMR","pub_key":"thorpub1addwnpepqvg02tp8umuqp36wy5ptpeqavkdu58gk0z8e7amnjyh3cpslfq9fqxhlmvp","address":"46aRdC5abaWj3jRyyCVsr8fdhSgyxhg2wfgnifctA1gAAvsMT4YiX48VhzUUNvDmdH4ucwpQouWXj7Dta95qCcC7SsxkZoP","halted":false,"global_trading_paused":false,"chain_trading_paused":false,"chain_lp_actions_paused":false,"observed_fee_rate":"8","gas_rate":"4","gas_rate_units":"atomic","outbound_tx_size":"250","outbound_fee":"355075","dust_threshold":"100000"}]
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ init_tests() {
|
|||
|
||||
d_ltc="overall operations with emulated RPC data (Litecoin)"
|
||||
t_ltc="
|
||||
- $cmdtest_py --coin=ltc --exclude regtest,autosign_automount,help,runeswap
|
||||
- $cmdtest_py --coin=ltc --exclude regtest,autosign_automount,help,runeswap,xmrswap
|
||||
- $cmdtest_py --coin=ltc --segwit
|
||||
- $cmdtest_py --coin=ltc --segwit-random
|
||||
- $cmdtest_py --coin=ltc --bech32
|
||||
|
|
@ -322,6 +322,8 @@ init_tests() {
|
|||
|
||||
d_xmr="Monero xmrwallet operations"
|
||||
t_xmr="
|
||||
- test/clean.py
|
||||
- ${xmr_env[*]} $cmdtest_py --coin=ltc xmrswap
|
||||
- ${xmr_env[*]} $cmdtest_py --coin=xmr --exclude help
|
||||
s ${xmr_env[*]} $cmdtest_py --coin=xmr xmr_autosign_nocompat
|
||||
"
|
||||
|
|
|
|||
Loading…
Reference in a new issue