Full Ethereum Classic (ETC) + ERC20 token support
As with ETH transacting support, this feature is in beta phase All key functionality works, for both ETC and ETC tokens: - Tracking wallet: getbalance, twview, listaddresses - TX create, send, sign - TX bumping - ERC20 token creation, deployment For usage details, see https://github.com/mmgen/mmgen/wiki/Altcoin-and-Forkcoin-Support Differences from ETH: - Start Parity with --jsonrpc-port=8555 (or --ports-shift=10) and --chain=classic - Launch MMGen commands with --coin=etc
This commit is contained in:
parent
5eb0bea794
commit
d4eb8f6ac0
10 changed files with 86 additions and 42 deletions
|
|
@ -33,7 +33,7 @@ class EthereumTrackingWallet(TrackingWallet):
|
|||
desc = 'Ethereum tracking wallet'
|
||||
caps = ()
|
||||
|
||||
data_dir = os.path.join(g.altcoin_data_dir,'eth',g.proto.data_subdir)
|
||||
data_dir = os.path.join(g.altcoin_data_dir,g.coin.lower(),g.proto.data_subdir)
|
||||
tw_file = os.path.join(data_dir,'tracking-wallet.json')
|
||||
|
||||
def __init__(self,mode='r'):
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ class EthereumMMGenTX(MMGenTX):
|
|||
|
||||
def is_in_wallet(self):
|
||||
d = g.rpch.eth_getTransactionReceipt('0x'+self.coin_txid)
|
||||
if d and 'blockNumber' in d:
|
||||
if d and 'blockNumber' in d and d['blockNumber'] is not None:
|
||||
return 1 + int(g.rpch.eth_blockNumber(),16) - int(d['blockNumber'],16)
|
||||
return False
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,11 @@ def check_daemons_running():
|
|||
ydie(1,fs.format(coin,g.proto.rpc_port))
|
||||
|
||||
def get_wallet_files():
|
||||
wfs = filter(lambda x: x[-6:] == '.mmdat',os.listdir(wallet_dir))
|
||||
m = "Cannot open wallet directory '{}'. Did you run 'mmgen-autosign setup'?"
|
||||
try: dlist = os.listdir(wallet_dir)
|
||||
except: die(1,m.format(wallet_dir))
|
||||
|
||||
wfs = filter(lambda x: x[-6:] == '.mmdat',dlist)
|
||||
if not wfs:
|
||||
die(1,'No wallet files present!')
|
||||
return [os.path.join(wallet_dir,w) for w in wfs]
|
||||
|
|
@ -143,8 +147,10 @@ def do_mount():
|
|||
msg('Mounting '+mountpoint)
|
||||
try:
|
||||
ds = os.stat(tx_dir)
|
||||
assert S_ISDIR(ds.st_mode)
|
||||
assert ds.st_mode & S_IWUSR|S_IRUSR == S_IWUSR|S_IRUSR
|
||||
m1 = "'{}' is not a directory!"
|
||||
m2 = "'{}' is not read/write for this user!"
|
||||
assert S_ISDIR(ds.st_mode),m1.format(tx_dir)
|
||||
assert ds.st_mode & S_IWUSR|S_IRUSR == S_IWUSR|S_IRUSR,m2.format(tx_dir)
|
||||
except:
|
||||
die(1,'{} missing, or not read/writable by user!'.format(tx_dir))
|
||||
|
||||
|
|
@ -168,15 +174,15 @@ def sign_tx_file(txfile):
|
|||
init_coin(tmp_tx.coin)
|
||||
|
||||
if hasattr(g.proto,'chain_name'):
|
||||
m = 'Protocol chain name ({}) does not match chain name from TX file ({})'
|
||||
assert tmp_tx.chain == g.proto.chain_name, m.format(tmp_tx.chain,g.proto.chain_name)
|
||||
m = 'Chains do not match! tx file: {}, proto: {}'
|
||||
assert tmp_tx.chain == g.proto.chain_name,m.format(tmp_tx.chain,g.proto.chain_name)
|
||||
|
||||
g.chain = tmp_tx.chain
|
||||
g.token = tmp_tx.dcoin
|
||||
g.dcoin = tmp_tx.dcoin or g.coin
|
||||
|
||||
reload(sys.modules['mmgen.tx'])
|
||||
if g.coin == 'ETH':
|
||||
if g.proto.base_coin == 'ETH':
|
||||
reload(sys.modules['mmgen.altcoins.eth.tx'])
|
||||
|
||||
tx = mmgen.tx.MMGenTX(txfile)
|
||||
|
|
|
|||
|
|
@ -343,14 +343,18 @@ class EthereumProtocol(DummyWIF,BitcoinProtocol):
|
|||
|
||||
class EthereumTestnetProtocol(EthereumProtocol):
|
||||
data_subdir = 'testnet'
|
||||
rpc_port = 8547 # start Parity with --ports-shift=2
|
||||
rpc_port = 8547 # start Parity with --jsonrpc-port=8547 or --ports-shift=2
|
||||
chain_name = 'kovan'
|
||||
|
||||
class EthereumClassicProtocol(EthereumProtocol):
|
||||
name = 'ethereum_classic'
|
||||
mmcaps = ('key','addr')
|
||||
name = 'ethereumClassic'
|
||||
class_pfx = 'Ethereum'
|
||||
rpc_port = 8555 # start Parity with --jsonrpc-port=8555 or --ports-shift=10
|
||||
chain_name = 'ethereum_classic' # chain_id 0x3d (61)
|
||||
|
||||
class EthereumClassicTestnetProtocol(EthereumClassicProtocol): pass
|
||||
class EthereumClassicTestnetProtocol(EthereumClassicProtocol):
|
||||
rpc_port = 8557 # start Parity with --jsonrpc-port=8557 or --ports-shift=12
|
||||
chain_name = 'classic-testnet' # aka Morden, chain_id 0x3e (62) (UNTESTED)
|
||||
|
||||
class ZcashProtocol(BitcoinProtocolAddrgen):
|
||||
name = 'zcash'
|
||||
|
|
@ -440,7 +444,7 @@ class CoinProtocol(MMGenObject):
|
|||
'bch': (BitcoinCashProtocol,BitcoinCashTestnetProtocol,None),
|
||||
'ltc': (LitecoinProtocol,LitecoinTestnetProtocol,None),
|
||||
'eth': (EthereumProtocol,EthereumTestnetProtocol,None),
|
||||
'etc': (EthereumClassicProtocol,EthereumClassicTestnetProtocol,2),
|
||||
'etc': (EthereumClassicProtocol,EthereumClassicTestnetProtocol,None),
|
||||
'zec': (ZcashProtocol,ZcashTestnetProtocol,2),
|
||||
'xmr': (MoneroProtocol,MoneroTestnetProtocol,None)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1126,7 +1126,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
import re
|
||||
d = literal_eval(re.sub(r"[A-Za-z]+?\(('.+?')\)",r'\1',raw_data))
|
||||
assert type(d) == list,'{} data not a list!'.format(desc)
|
||||
if not (desc == 'outputs' and g.coin == 'ETH'): # ETH txs can have no outputs
|
||||
if not (desc == 'outputs' and g.proto.base_coin == 'ETH'): # ETH txs can have no outputs
|
||||
assert len(d),'no {}!'.format(desc)
|
||||
for e in d: e['amt'] = g.proto.coin_amt(e['amt'])
|
||||
io,io_list = (
|
||||
|
|
|
|||
|
|
@ -849,7 +849,7 @@ def rpc_init_parity():
|
|||
|
||||
if not g.daemon_version: # First call
|
||||
g.daemon_version = g.rpch.parity_versionInfo()['version'] # fail immediately if daemon is geth
|
||||
g.chain = g.rpch.parity_chain()
|
||||
g.chain = g.rpch.parity_chain().replace(' ','_')
|
||||
if g.token:
|
||||
(g.token,g.dcoin) = resolve_token_arg(g.token)
|
||||
|
||||
|
|
@ -923,10 +923,11 @@ def format_par(s,indent=0,width=80,as_list=False):
|
|||
# module loading magic for tx.py and tw.py
|
||||
def altcoin_subclass(cls,mod_id,cls_name):
|
||||
if cls.__name__ != cls_name: return cls
|
||||
pn = capfirst(g.proto.name)
|
||||
tn = 'Token' if g.token else ''
|
||||
e1 = 'from mmgen.altcoins.{}.{} import {}{}{}'.format(g.coin.lower(),mod_id,pn,tn,cls_name)
|
||||
e2 = 'cls = {}{}{}'.format(pn,tn,cls_name)
|
||||
mod_dir = g.proto.base_coin.lower()
|
||||
pname = g.proto.class_pfx if hasattr(g.proto,'class_pfx') else capfirst(g.proto.name)
|
||||
tname = 'Token' if g.token else ''
|
||||
e1 = 'from mmgen.altcoins.{}.{} import {}{}{}'.format(mod_dir,mod_id,pname,tname,cls_name)
|
||||
e2 = 'cls = {}{}{}'.format(pname,tname,cls_name)
|
||||
try: exec e1; exec e2; return cls
|
||||
except ImportError: return cls
|
||||
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ opts_data = lambda: {
|
|||
""".format(d=decimals,n=name,s=symbol,t=supply)
|
||||
}
|
||||
|
||||
g.coin = 'ETH'
|
||||
cmd_args = opts.init(opts_data)
|
||||
assert g.coin in ('ETH','ETC'),'--coin option must be set to ETH or ETC'
|
||||
|
||||
if not len(cmd_args) == 1 or not is_coin_addr(cmd_args[0]):
|
||||
opts.usage()
|
||||
|
|
|
|||
|
|
@ -208,11 +208,13 @@ t_monero=(
|
|||
f_monero='Monero tests completed'
|
||||
|
||||
i_eth='Ethereum'
|
||||
s_eth='Testing transaction and tracking wallet operations for Ethereum'
|
||||
s_eth='Testing transaction and tracking wallet operations for Ethereum and Ethereum Classic'
|
||||
t_eth=(
|
||||
"$test_py -On --coin=eth ref_tx_chk"
|
||||
"$test_py -On --coin=eth --testnet=1 ref_tx_chk"
|
||||
"$test_py -On ethdev"
|
||||
"$test_py -On --coin=etc ref_tx_chk"
|
||||
"$test_py -On --coin=eth ethdev"
|
||||
"$test_py -On --coin=etc ethdev"
|
||||
)
|
||||
f_eth='Ethereum tests completed'
|
||||
|
||||
|
|
|
|||
6
test/ref/ethereum_classic/ED3848-ETC[1.2345,40000].rawtx
Normal file
6
test/ref/ethereum_classic/ED3848-ETC[1.2345,40000].rawtx
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
aa0148
|
||||
ETC ETHEREUM_CLASSIC ED3848 1.2345 20181002_000000 6670000
|
||||
{"nonce": "0", "chainId": "61", "from": "1a6acbef8c38f52f20d04ecded2992b04d8608d7", "startGas": "0.000000000000021", "to": "61d7cba023f6131df1ade460880fee75df3987c4", "data": "", "amt": "1.2345", "gasPrice": "0.00000004"}
|
||||
[{'confs': 0, 'label': u'', 'mmid': '98831F3A:E:1', 'amt': '123.456', 'addr': '1a6acbef8c38f52f20d04ecded2992b04d8608d7'}]
|
||||
[{'mmid': '98831F3A:E:2', 'amt': '1.2345', 'addr': '61d7cba023f6131df1ade460880fee75df3987c4'}]
|
||||
TvwWgaAnrkQFpAxxjBa4PHvJ8NsJDsurtiv2HuzdnXWjQmY7LHyt6PZn5J7BNtB5VzHtBG7bUosCAMFon8yxUe2mYTZoH9e6dpoAz9E6JDZtUNYz9YnF1Z3jFND1X89RuKAk6YVBrfWseeyHR8vZDdaFzBPK5SPos
|
||||
65
test/test.py
65
test/test.py
|
|
@ -163,13 +163,12 @@ opt.popen_spawn = True # popen has issues, so use popen_spawn always
|
|||
|
||||
if not opt.system: os.environ['PYTHONPATH'] = repo_root
|
||||
|
||||
ref_subdir = '' if g.proto.base_coin == 'BTC' else g.proto.name
|
||||
ref_subdir = '' if g.proto.base_coin == 'BTC' else 'ethereum_classic' if g.coin == 'ETC' else g.proto.name
|
||||
altcoin_pfx = '' if g.proto.base_coin == 'BTC' else '-'+g.proto.base_coin
|
||||
tn_ext = ('','.testnet')[g.testnet]
|
||||
|
||||
coin_sel = g.coin.lower()
|
||||
# if g.coin == 'B2X': coin_sel = 'btc'
|
||||
if g.coin == 'ETH': coin_sel = 'btc' # TODO
|
||||
if g.coin.lower() in ('eth','etc'): coin_sel = 'btc'
|
||||
|
||||
fork = {'bch':'btc','btc':'btc','ltc':'ltc'}[coin_sel]
|
||||
tx_fee = {'btc':'0.0001','bch':'0.001','ltc':'0.01'}[coin_sel]
|
||||
|
|
@ -585,7 +584,8 @@ cfgs = {
|
|||
'eth': ('88FEFD-ETH[23.45495,40000].rawtx',
|
||||
'B472BD-ETH[23.45495,40000].testnet.rawtx'),
|
||||
'erc20': ('5881D2-MM1[1.23456,50000].rawtx',
|
||||
'6BDB25-MM1[1.23456,50000].testnet.rawtx')
|
||||
'6BDB25-MM1[1.23456,50000].testnet.rawtx'),
|
||||
'etc': ('ED3848-ETC[1.2345,40000].rawtx','')
|
||||
},
|
||||
'ic_wallet': u'98831F3A-5482381C-18460FB1[256,1].mmincog',
|
||||
'ic_wallet_hex': u'98831F3A-1630A9F2-870376A9[256,1].mmincox',
|
||||
|
|
@ -872,7 +872,7 @@ cmd_group['regtest_split'] = (
|
|||
)
|
||||
|
||||
cmd_group['ethdev'] = (
|
||||
('ethdev_setup', 'Ethereum Parity dev mode tests (start parity)'),
|
||||
('ethdev_setup', 'Ethereum Parity dev mode tests for coin {} (start parity)'.format(g.coin)),
|
||||
('ethdev_addrgen', 'generating addresses'),
|
||||
('ethdev_addrimport', 'importing addresses'),
|
||||
('ethdev_addrimport_dev_addr', "importing Parity dev address 'Ox00a329c..'"),
|
||||
|
|
@ -934,6 +934,8 @@ cmd_group['ethdev'] = (
|
|||
('ethdev_token_txsign1', 'signing the transaction'),
|
||||
('ethdev_token_txsend1', 'sending the transaction'),
|
||||
|
||||
('ethdev_token_twview1', 'viewing token tracking wallet'),
|
||||
|
||||
('ethdev_token_txcreate2', 'creating a token transaction (to burn address)'),
|
||||
('ethdev_token_txbump', 'bumping the transaction fee'),
|
||||
|
||||
|
|
@ -942,8 +944,8 @@ cmd_group['ethdev'] = (
|
|||
|
||||
('ethdev_del_dev_addr', "deleting the dev address"),
|
||||
|
||||
('ethdev_bal2', 'the ETH balance'),
|
||||
('ethdev_bal2_getbalance', 'the ETH balance (getbalance)'),
|
||||
('ethdev_bal2', 'the {} balance'.format(g.coin)),
|
||||
('ethdev_bal2_getbalance', 'the {} balance (getbalance)'.format(g.coin)),
|
||||
|
||||
('ethdev_addrimport_token_burn_addr',"importing the token burn address"),
|
||||
|
||||
|
|
@ -955,7 +957,7 @@ cmd_group['ethdev'] = (
|
|||
('ethdev_txsend_noamt', 'sending the transaction'),
|
||||
|
||||
('ethdev_token_bal2', 'the token balance'),
|
||||
('ethdev_bal3', 'the ETH balance'),
|
||||
('ethdev_bal3', 'the {} balance'.format(g.coin)),
|
||||
|
||||
('ethdev_token_txcreate_noamt', 'creating a token transaction (full amount send)'),
|
||||
('ethdev_token_txsign_noamt', 'signing the transaction'),
|
||||
|
|
@ -967,7 +969,7 @@ cmd_group['ethdev'] = (
|
|||
)
|
||||
|
||||
cmd_group['autosign'] = (
|
||||
('autosign', 'transaction autosigning (BTC,BCH,LTC)'),
|
||||
('autosign', 'transaction autosigning (BTC,BCH,LTC,ETH,ETC)'),
|
||||
)
|
||||
|
||||
cmd_group['ref_alt'] = (
|
||||
|
|
@ -2319,14 +2321,20 @@ class MMGenTestSuite(object):
|
|||
|
||||
def autosign(self,name): # tests everything except device detection, mount/unmount
|
||||
if skip_for_win(): return
|
||||
fdata = (('btc',''),('bch',''),('ltc','litecoin'),('eth','ethereum'),('erc20','ethereum'))
|
||||
fdata = ( ('btc',''),
|
||||
('bch',''),
|
||||
('ltc','litecoin'),
|
||||
('eth','ethereum'),
|
||||
('erc20','ethereum'),
|
||||
('etc','ethereum_classic'))
|
||||
tfns = [cfgs['8']['ref_tx_file'][c][1] for c,d in fdata] + \
|
||||
[cfgs['8']['ref_tx_file'][c][0] for c,d in fdata]
|
||||
tfs = [os.path.join(ref_dir,d[1],fn) for d,fn in zip(fdata+fdata,tfns)]
|
||||
try: os.mkdir(os.path.join(cfg['tmpdir'],'tx'))
|
||||
except: pass
|
||||
for f,fn in zip(tfs,tfns):
|
||||
shutil.copyfile(f,os.path.join(cfg['tmpdir'],'tx',fn))
|
||||
if fn: # use empty fn to skip file
|
||||
shutil.copyfile(f,os.path.join(cfg['tmpdir'],'tx',fn))
|
||||
# make a bad tx file
|
||||
with open(os.path.join(cfg['tmpdir'],'tx','bad.rawtx'),'w') as f:
|
||||
f.write('bad tx data')
|
||||
|
|
@ -2347,7 +2355,7 @@ class MMGenTestSuite(object):
|
|||
t.ok()
|
||||
|
||||
t = MMGenExpect(name,'mmgen-autosign',opts+['wait'],extra_desc='(sign)')
|
||||
t.expect('10 transactions signed')
|
||||
t.expect('11 transactions signed')
|
||||
t.expect('1 transaction failed to sign')
|
||||
t.expect('Waiting.')
|
||||
t.kill(2)
|
||||
|
|
@ -2596,7 +2604,9 @@ class MMGenTestSuite(object):
|
|||
# self.txcreate_common(name,sources=['8'])
|
||||
|
||||
def ref_tx_chk(self,name):
|
||||
tf = os.path.join(ref_dir,ref_subdir,cfg['ref_tx_file'][g.coin.lower()][bool(tn_ext)])
|
||||
fn = cfg['ref_tx_file'][g.coin.lower()][bool(tn_ext)]
|
||||
if not fn: return
|
||||
tf = os.path.join(ref_dir,ref_subdir,fn)
|
||||
wf = dfl_words
|
||||
write_to_tmpfile(cfg,pwfile,cfg['wpasswd'])
|
||||
pf = get_tmpfile_fn(cfg,pwfile)
|
||||
|
|
@ -3213,7 +3223,7 @@ class MMGenTestSuite(object):
|
|||
|
||||
def ethdev_txcreate(self,name,args=[],menu=[],acct='1',non_mmgen_inputs=0,
|
||||
interactive_fee='50G',
|
||||
fee_res='0.00105 ETH (50 gas price in Gwei)',
|
||||
fee_res='0.00105 {} (50 gas price in Gwei)'.format(g.coin),
|
||||
fee_desc = 'gas price'):
|
||||
t = MMGenExpect(name,'mmgen-txcreate', eth_args() + ['-B'] + args)
|
||||
t.expect(r"'q'=quit view, .*?:.",'p', regex=True)
|
||||
|
|
@ -3274,7 +3284,7 @@ class MMGenTestSuite(object):
|
|||
def ethdev_txcreate4(self,name):
|
||||
args = ['98831F3A:E:2,23.45495']
|
||||
interactive_fee='40G'
|
||||
fee_res='0.00084 ETH (40 gas price in Gwei)'
|
||||
fee_res='0.00084 {} (40 gas price in Gwei)'.format(g.coin)
|
||||
return self.ethdev_txcreate(name,args=args,acct='1',non_mmgen_inputs=0,
|
||||
interactive_fee=interactive_fee,fee_res=fee_res)
|
||||
|
||||
|
|
@ -3329,7 +3339,7 @@ class MMGenTestSuite(object):
|
|||
|
||||
def init_ethdev_common(self):
|
||||
g.testnet = True
|
||||
init_coin('eth')
|
||||
init_coin(g.coin)
|
||||
g.proto.rpc_port = 8549
|
||||
rpc_init()
|
||||
|
||||
|
|
@ -3338,7 +3348,7 @@ class MMGenTestSuite(object):
|
|||
cmd_args = ['--{}={}'.format(k,v) for k,v in token_data.items()]
|
||||
silence()
|
||||
imsg("Compiling solidity token contract '{}' with 'solc'".format(token_data['symbol']))
|
||||
cmd = ['scripts/create-token.py','--outdir='+cfg['tmpdir']] + cmd_args + [eth_addr]
|
||||
cmd = ['scripts/create-token.py','--coin='+g.coin,'--outdir='+cfg['tmpdir']] + cmd_args + [eth_addr]
|
||||
imsg("Executing: {}".format(' '.join(cmd)))
|
||||
subprocess.check_output(cmd)
|
||||
imsg("ERC20 token '{}' compiled".format(token_data['symbol']))
|
||||
|
|
@ -3386,7 +3396,7 @@ class MMGenTestSuite(object):
|
|||
def ethdev_token_deploy1c(self,name): self.ethdev_token_deploy(name,num=1,key='Token',gas=1100000,tx_fee='7G')
|
||||
|
||||
def ethdev_tx_status2(self,name):
|
||||
self.ethdev_tx_status(name,ext='ETH[0,7000].sigtx',expect_str='successfully executed')
|
||||
self.ethdev_tx_status(name,ext=g.coin+'[0,7000].sigtx',expect_str='successfully executed')
|
||||
|
||||
def ethdev_token_deploy2a(self,name): self.ethdev_token_deploy(name,num=2,key='SafeMath',gas=200000)
|
||||
def ethdev_token_deploy2b(self,name): self.ethdev_token_deploy(name,num=2,key='Owned',gas=250000)
|
||||
|
|
@ -3398,7 +3408,7 @@ class MMGenTestSuite(object):
|
|||
def ethdev_token_transfer_funds(self,name):
|
||||
MMGenExpect(name,'',msg_only=True)
|
||||
sid = cfgs['8']['seed_id']
|
||||
cmd = lambda i: ['mmgen-tool','--coin=eth','gen_addr','{}:E:{}'.format(sid,i),'wallet='+dfl_words]
|
||||
cmd = lambda i: ['mmgen-tool','--coin='+g.coin,'gen_addr','{}:E:{}'.format(sid,i),'wallet='+dfl_words]
|
||||
silence()
|
||||
usr_addrs = [subprocess.check_output(cmd(i),stderr=sys.stderr).strip() for i in 11,21]
|
||||
self.init_ethdev_common()
|
||||
|
|
@ -3443,6 +3453,19 @@ class MMGenTestSuite(object):
|
|||
def ethdev_token_txsend1(self,name):
|
||||
self.ethdev_token_txsend(name,ext='1.23456,50000].sigtx',token='mm1')
|
||||
|
||||
def ethdev_twview(self,name,args,expect_str):
|
||||
t = MMGenExpect(name,'mmgen-tool', eth_args() + args + ['twview'])
|
||||
t.expect(expect_str,regex=True)
|
||||
t.read()
|
||||
t.ok()
|
||||
|
||||
bal_corr = Decimal('0.0000032') # gas use varies for token sends!
|
||||
def ethdev_token_twview1(self,name):
|
||||
ebal = Decimal('1.2314236')
|
||||
if g.coin == 'ETC': ebal += self.bal_corr
|
||||
s = '98831F3A:E:11\s+998.76544\s+' + str(ebal)
|
||||
return self.ethdev_twview(name,args=['--token=mm1'],expect_str=s)
|
||||
|
||||
def ethdev_token_txcreate2(self,name):
|
||||
return self.ethdev_token_txcreate(name,args=[eth_burn_addr+','+eth_amt2],token='mm1')
|
||||
|
||||
|
|
@ -3466,7 +3489,9 @@ class MMGenTestSuite(object):
|
|||
self.ethdev_bal(name,expect_str=r'deadbeef.* 999999.12345689012345678')
|
||||
|
||||
def ethdev_bal2_getbalance(self,name,t_non_mmgen='',t_mmgen=''):
|
||||
self.ethdev_bal_getbalance(name,t_non_mmgen='999999.12345689012345678',t_mmgen='127.0287876')
|
||||
ebal = Decimal('127.0287876')
|
||||
if g.coin == 'ETC': ebal += self.bal_corr
|
||||
self.ethdev_bal_getbalance(name,t_non_mmgen='999999.12345689012345678',t_mmgen=str(ebal))
|
||||
|
||||
def ethdev_token_bal(self,name,expect_str):
|
||||
t = MMGenExpect(name,'mmgen-tool', eth_args() + ['--token=mm1','twview','wide=1'])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue