From 8b6bdc72caf0669530a61bebacf07fd1f50d5ca9 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Sat, 3 Dec 2022 17:40:43 +0000 Subject: [PATCH] new class: ETCAmt; ETHAmt -> proto.coin_amt --- mmgen/amt.py | 3 +++ mmgen/proto/etc/params.py | 1 + mmgen/proto/eth/contract.py | 5 ++--- mmgen/proto/eth/tw/ctl.py | 3 +-- mmgen/proto/eth/tw/json.py | 3 +-- mmgen/proto/eth/tx/base.py | 17 ++++++++--------- mmgen/proto/eth/tx/bump.py | 3 +-- mmgen/proto/eth/tx/completed.py | 7 +++++++ mmgen/proto/eth/tx/new.py | 19 +++++++++++-------- mmgen/proto/eth/tx/signed.py | 7 +++---- mmgen/proto/eth/tx/unsigned.py | 7 +++---- test/test_py_d/ts_ethdev.py | 9 ++++----- 12 files changed, 45 insertions(+), 39 deletions(-) diff --git a/mmgen/amt.py b/mmgen/amt.py index 9568d998..80c89f90 100755 --- a/mmgen/amt.py +++ b/mmgen/amt.py @@ -191,3 +191,6 @@ class ETHAmt(CoinAmt): def toWei(self): return int(Decimal(self) // self.wei) + +class ETCAmt(ETHAmt): + coin = 'ETC' diff --git a/mmgen/proto/etc/params.py b/mmgen/proto/etc/params.py index 79ddde07..345fad40 100755 --- a/mmgen/proto/etc/params.py +++ b/mmgen/proto/etc/params.py @@ -17,6 +17,7 @@ from ..eth.params import mainnet class mainnet(mainnet): chain_names = ['classic','ethereum_classic'] max_tx_fee = '0.005' + coin_amt = 'ETCAmt' ignore_daemon_version = False class testnet(mainnet): diff --git a/mmgen/proto/eth/contract.py b/mmgen/proto/eth/contract.py index 458a9f96..84532ed7 100755 --- a/mmgen/proto/eth/contract.py +++ b/mmgen/proto/eth/contract.py @@ -29,7 +29,6 @@ from ...globalvars import g from ...base_obj import AsyncInit from ...obj import MMGenObject,CoinTxID from ...addr import CoinAddr,TokenAddr -from ...amt import ETHAmt def parse_abi(s): return [s[:8]] + [s[8+x*64:8+(x+1)*64] for x in range(len(s[8:])//64)] @@ -43,7 +42,7 @@ class TokenCommon(MMGenObject): return CoinAddr(self.proto,parse_abi(data)[1][-40:]) def transferdata2amt(self,data): # online - return ETHAmt(int(parse_abi(data)[-1],16) * self.base_unit) + return self.proto.coin_amt(int(parse_abi(data)[-1],16) * self.base_unit) async def do_call(self,method_sig,method_args='',toUnit=False): data = self.create_method_id(method_sig) + method_args @@ -59,7 +58,7 @@ class TokenCommon(MMGenObject): return ret async def get_balance(self,acct_addr): - return ETHAmt(await self.do_call('balanceOf(address)',acct_addr.rjust(64,'0'),toUnit=True)) + return self.proto.coin_amt(await self.do_call('balanceOf(address)',acct_addr.rjust(64,'0'),toUnit=True)) def strip(self,s): return ''.join([chr(b) for b in s if 32 <= b <= 127]).strip() diff --git a/mmgen/proto/eth/tw/ctl.py b/mmgen/proto/eth/tw/ctl.py index b0ba3f13..f17f3720 100755 --- a/mmgen/proto/eth/tw/ctl.py +++ b/mmgen/proto/eth/tw/ctl.py @@ -23,7 +23,6 @@ proto.eth.tw.ctl: Ethereum tracking wallet control class from ....util import msg,ymsg,die from ....tw.ctl import TwCtl,write_mode from ....addr import is_coin_addr,is_mmgen_id -from ....amt import ETHAmt from ..contract import Token,TokenResolve class EthereumTwCtl(TwCtl): @@ -82,7 +81,7 @@ class EthereumTwCtl(TwCtl): msg(f'{self.desc} upgraded successfully!') async def rpc_get_balance(self,addr): - return ETHAmt(int(await self.rpc.call('eth_getBalance','0x'+addr,'latest'),16),'wei') + return self.proto.coin_amt(int(await self.rpc.call('eth_getBalance','0x'+addr,'latest'),16),'wei') @write_mode async def batch_import_address(self,args_list): diff --git a/mmgen/proto/eth/tw/json.py b/mmgen/proto/eth/tw/json.py index 7c19eaae..9680cb17 100755 --- a/mmgen/proto/eth/tw/json.py +++ b/mmgen/proto/eth/tw/json.py @@ -143,5 +143,4 @@ class EthereumTwJSON(TwJSON): @property async def total(self): - from ....amt import ETHAmt - return sum(ETHAmt(i.amount) for i in self.entries['accounts']) or ETHAmt('0') + return sum(self.proto.coin_amt(i.amount) for i in self.entries['accounts']) or self.proto.coin_amt('0') diff --git a/mmgen/proto/eth/tx/base.py b/mmgen/proto/eth/tx/base.py index 89544f9f..97f94c28 100755 --- a/mmgen/proto/eth/tx/base.py +++ b/mmgen/proto/eth/tx/base.py @@ -15,7 +15,6 @@ proto.eth.tx.base: Ethereum base transaction class from collections import namedtuple import mmgen.tx.base as TxBase -from ....amt import ETHAmt from ....obj import HexStr,Int from ....util import dmsg @@ -24,23 +23,23 @@ class Base(TxBase.Base): rel_fee_desc = 'gas price' rel_fee_disp = 'gas price in Gwei' txobj = None # "" - gas = ETHAmt(21000,'wei') # an approximate number, used for fee estimation purposes - start_gas = ETHAmt(21000,'wei') # the actual startgas amt used in the transaction - # for simple sends with no data, gas = start_gas = 21000 + dfl_gas = 21000 # an approximate number, used for fee estimation purposes + dfl_start_gas = 21000 # the actual startgas amt used in the transaction + # for simple sends with no data, gas = start_gas = 21000 contract_desc = 'contract' usr_contract_data = HexStr('') disable_fee_check = False # given absolute fee in ETH, return gas price in Gwei using self.gas def fee_abs2rel(self,abs_fee,to_unit='Gwei'): - ret = ETHAmt(int(abs_fee.toWei() // self.gas.toWei()),'wei') + ret = self.proto.coin_amt(int(abs_fee.toWei() // self.gas.toWei()),'wei') dmsg(f'fee_abs2rel() ==> {ret} ETH') return ret if to_unit == 'eth' else ret.to_unit(to_unit,show_decimal=True) # given rel fee (gasPrice) in wei, return absolute fee using self.gas (Ethereum-only method) def fee_gasPrice2abs(self,rel_fee): assert isinstance(rel_fee,int), f'{rel_fee!r}: incorrect type for fee estimate (not an integer)' - return ETHAmt(rel_fee * self.gas.toWei(),'wei') + return self.proto.coin_amt(rel_fee * self.gas.toWei(),'wei') def is_replaceable(self): return True @@ -54,7 +53,7 @@ class Base(TxBase.Base): status = Int(rx['status'],16), # zero is failure, non-zero success gas_sent = Int(tx['gas'],16), gas_used = Int(rx['gasUsed'],16), - gas_price = ETHAmt(int(tx['gasPrice'],16),from_unit='wei'), + gas_price = self.proto.coin_amt(int(tx['gasPrice'],16),from_unit='wei'), contract_addr = self.proto.coin_addr(rx['contractAddress'][2:]) if rx['contractAddress'] else None, tx = tx, rx = rx, @@ -64,6 +63,6 @@ class Base(TxBase.Base): return True class TokenBase(Base): - gas = ETHAmt(52000,'wei') - start_gas = ETHAmt(60000,'wei') + dfl_gas = 52000 + dfl_start_gas = 60000 contract_desc = 'token contract' diff --git a/mmgen/proto/eth/tx/bump.py b/mmgen/proto/eth/tx/bump.py index f2a27a70..9e6539e1 100755 --- a/mmgen/proto/eth/tx/bump.py +++ b/mmgen/proto/eth/tx/bump.py @@ -15,7 +15,6 @@ proto.eth.tx.bump: Ethereum transaction bump class import mmgen.tx.bump as TxBase from .completed import Completed,TokenCompleted from .new import New,TokenNew -from ....amt import ETHAmt from decimal import Decimal class Bump(Completed,New,TxBase.Bump): @@ -23,7 +22,7 @@ class Bump(Completed,New,TxBase.Bump): @property def min_fee(self): - return ETHAmt(self.fee * Decimal('1.101')) + return self.proto.coin_amt(self.fee * Decimal('1.101')) def bump_fee(self,idx,fee): self.txobj['gasPrice'] = self.fee_abs2rel(fee,to_unit='eth') diff --git a/mmgen/proto/eth/tx/completed.py b/mmgen/proto/eth/tx/completed.py index 506b314b..77fda511 100755 --- a/mmgen/proto/eth/tx/completed.py +++ b/mmgen/proto/eth/tx/completed.py @@ -18,6 +18,13 @@ from .base import Base,TokenBase class Completed(Base,TxBase.Completed): fn_fee_unit = 'Mwei' + def __init__(self,*args,**kwargs): + + super().__init__(*args,**kwargs) + + self.gas = self.proto.coin_amt(self.dfl_gas,'wei') + self.start_gas = self.proto.coin_amt(self.dfl_start_gas,'wei') + @property def send_amt(self): return self.outputs[0].amt if self.outputs else self.proto.coin_amt('0') diff --git a/mmgen/proto/eth/tx/new.py b/mmgen/proto/eth/tx/new.py index 15c76635..9f669a61 100755 --- a/mmgen/proto/eth/tx/new.py +++ b/mmgen/proto/eth/tx/new.py @@ -18,7 +18,6 @@ import mmgen.tx.new as TxBase from .base import Base,TokenBase from ....opts import opt from ....obj import Int,ETHNonce,MMGenTxID,Str,HexStr -from ....amt import ETHAmt from ....util import msg,is_int,is_hex_str,make_chksum_6 from ....tw.ctl import TwCtl from ....addr import is_mmgen_id,is_coin_addr @@ -36,7 +35,11 @@ class New(Base,TxBase.New): super().__init__(*args,**kwargs) if opt.gas: - self.gas = self.start_gas = ETHAmt(int(opt.gas),'wei') + self.gas = self.start_gas = self.proto.coin_amt(int(opt.gas),'wei') + else: + self.gas = self.proto.coin_amt(self.dfl_gas,'wei') + self.start_gas = self.proto.coin_amt(self.dfl_start_gas,'wei') + if opt.contract_data: m = "'--contract-data' option may not be used with token transaction" assert not 'Token' in type(self).__name__, m @@ -51,7 +54,7 @@ class New(Base,TxBase.New): self.txobj = { 'from': self.inputs[0].addr, 'to': self.outputs[0].addr if self.outputs else Str(''), - 'amt': self.outputs[0].amt if self.outputs else ETHAmt('0'), + 'amt': self.outputs[0].amt if self.outputs else self.proto.coin_amt('0'), 'gasPrice': self.fee_abs2rel(self.usr_fee,to_unit='eth'), 'startGas': self.start_gas, 'nonce': await self.get_nonce(), @@ -111,8 +114,8 @@ class New(Base,TxBase.New): # given rel fee and units, return absolute fee using self.gas def fee_rel2abs(self,tx_size,units,amt,unit): - return ETHAmt( - ETHAmt(amt,units[unit]).toWei() * self.gas.toWei(), + return self.proto.coin_amt( + self.proto.coin_amt(amt,units[unit]).toWei() * self.gas.toWei(), from_unit='wei' ) @@ -139,7 +142,7 @@ class New(Base,TxBase.New): def update_change_output(self,funds_left): if self.outputs and self.outputs[0].is_chg: - self.update_output_amt(0,ETHAmt(funds_left)) + self.update_output_amt(0,self.proto.coin_amt(funds_left)) async def get_input_addrs_from_cmdline(self): ret = [] @@ -165,7 +168,7 @@ class New(Base,TxBase.New): def final_inputs_ok_msg(self,funds_left): chg = '0' if (self.outputs and self.outputs[0].is_chg) else funds_left return 'Transaction leaves {} {} in the sender’s account'.format( - ETHAmt(chg).hl(), + self.proto.coin_amt(chg).hl(), self.proto.coin ) @@ -200,7 +203,7 @@ class TokenNew(TokenBase,New): def final_inputs_ok_msg(self,funds_left): token_bal = ( - ETHAmt('0') if self.outputs[0].is_chg + self.proto.coin_amt('0') if self.outputs[0].is_chg else self.inputs[0].amt - self.outputs[0].amt ) return "Transaction leaves ≈{} {} and {} {} in the sender's account".format( diff --git a/mmgen/proto/eth/tx/signed.py b/mmgen/proto/eth/tx/signed.py index f6e822d1..e1d34497 100755 --- a/mmgen/proto/eth/tx/signed.py +++ b/mmgen/proto/eth/tx/signed.py @@ -17,7 +17,6 @@ from .completed import Completed,TokenCompleted from ..contract import Token from ....obj import Str,CoinTxID,ETHNonce,HexStr from ....addr import CoinAddr,TokenAddr -from ....amt import ETHAmt class Signed(Completed,TxBase.Signed): @@ -35,9 +34,9 @@ class Signed(Completed,TxBase.Signed): 'from': CoinAddr(self.proto,d['sender']), # NB: for token, 'to' is token address 'to': CoinAddr(self.proto,d['to']) if d['to'] else Str(''), - 'amt': ETHAmt(d['value'],'wei'), - 'gasPrice': ETHAmt(d['gasprice'],'wei'), - 'startGas': ETHAmt(d['startgas'],'wei'), + 'amt': self.proto.coin_amt(d['value'],'wei'), + 'gasPrice': self.proto.coin_amt(d['gasprice'],'wei'), + 'startGas': self.proto.coin_amt(d['startgas'],'wei'), 'nonce': ETHNonce(d['nonce']), 'data': HexStr(d['data']) } if o['data'] and not o['to']: # token- or contract-creating transaction diff --git a/mmgen/proto/eth/tx/unsigned.py b/mmgen/proto/eth/tx/unsigned.py index 4bc14a84..6e4a67db 100755 --- a/mmgen/proto/eth/tx/unsigned.py +++ b/mmgen/proto/eth/tx/unsigned.py @@ -20,7 +20,6 @@ from ..contract import Token from ....util import msg,msg_r,ymsg from ....obj import Str,CoinTxID,ETHNonce,Int,HexStr from ....addr import CoinAddr,TokenAddr -from ....amt import ETHAmt class Unsigned(Completed,TxBase.Unsigned): desc = 'unsigned transaction' @@ -32,9 +31,9 @@ class Unsigned(Completed,TxBase.Unsigned): 'from': CoinAddr(self.proto,d['from']), # NB: for token, 'to' is sendto address 'to': CoinAddr(self.proto,d['to']) if d['to'] else Str(''), - 'amt': ETHAmt(d['amt']), - 'gasPrice': ETHAmt(d['gasPrice']), - 'startGas': ETHAmt(d['startGas']), + 'amt': self.proto.coin_amt(d['amt']), + 'gasPrice': self.proto.coin_amt(d['gasPrice']), + 'startGas': self.proto.coin_amt(d['startGas']), 'nonce': ETHNonce(d['nonce']), 'chainId': None if d['chainId'] == 'None' else Int(d['chainId']), 'data': HexStr(d['data']) } diff --git a/test/test_py_d/ts_ethdev.py b/test/test_py_d/ts_ethdev.py index a7140ba9..a67a5253 100755 --- a/test/test_py_d/ts_ethdev.py +++ b/test/test_py_d/ts_ethdev.py @@ -28,7 +28,6 @@ from subprocess import run,PIPE,DEVNULL from mmgen.globalvars import g from mmgen.opts import opt from mmgen.util import die -from mmgen.amt import ETHAmt from mmgen.protocol import CoinProtocol from ..include.common import * from .common import * @@ -40,8 +39,6 @@ dfl_sid = '98831F3A' dfl_devaddr = '00a329c0648769a73afac7f9381e08fb43dbea72' dfl_devkey = '4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7' -prealloc_amt = ETHAmt('1_000_000_000') - burn_addr = 'deadbeef'*5 burn_addr2 = 'beadcafe'*5 @@ -509,6 +506,8 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared): imsg(cyan('Initializing Genesis Block:')) + prealloc_amt = self.proto.coin_amt('1_000_000_000') + make_key() signer_addr = self.keystore_data['address'] self.write_to_tmpfile( 'signer_addr', signer_addr + '\n' ) @@ -989,8 +988,8 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared): usr_addrs[i], amt, dfl_devkey, - start_gas = ETHAmt(60000,'wei'), - gasPrice = ETHAmt(8,'Gwei') ) + start_gas = self.proto.coin_amt(60000,'wei'), + gasPrice = self.proto.coin_amt(8,'Gwei') ) if self.daemon.id == 'geth': # yet another Geth bug await asyncio.sleep(0.5) if (await self.get_tx_receipt(txid)).status == 0: