proto.eth.tx: make self.gas an integer

This commit is contained in:
The MMGen Project 2025-05-07 18:24:07 +00:00
commit 8d33c6d4a9
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
10 changed files with 55 additions and 30 deletions

View file

@ -57,7 +57,8 @@ opts_data = {
+ {fu} (an integer followed by {fl}).
+ See FEE SPECIFICATION below. If omitted, fee will be
+ calculated using network fee estimation.
e- -g, --gas= g Specify start gas amount in Wei
et -g, --gas=N Specify gas limit (integer)
-s -g, --gas=N Specify gas limit for Ethereum (integer)
-- -i, --info Display {a_info} and exit
-- -I, --inputs= i Specify transaction inputs (comma-separated list of
+ MMGen IDs or coin addresses). Note that ALL unspent

View file

@ -57,7 +57,8 @@ opts_data = {
+ {fu} (an integer followed by {fl!r}).
+ See FEE SPECIFICATION below. If omitted, fee will be
+ calculated using network fee estimation.
e- -g, --gas= g Specify start gas amount in Wei
et -g, --gas=N Specify gas limit (integer)
-s -g, --gas=N Specify gas limit for Ethereum (integer)
-- -H, --hidden-incog-input-params=f,o Read hidden incognito data from file
+ 'f' at offset 'o' (comma-separated)
-- -i, --in-fmt= f Input is from wallet format 'f' (see FMT CODES below)

View file

@ -67,9 +67,10 @@ class Contract:
return ret
def make_tx_in(self, *, gas, gasPrice, nonce, data):
assert isinstance(gas, int), f'{type(gas)}: incorrect type for ‘gas’ (must be an int)'
return {
'to': bytes.fromhex(self.addr),
'startgas': gas.toWei(),
'startgas': gas,
'gasprice': gasPrice.toWei(),
'value': 0,
'nonce': nonce,

View file

@ -44,12 +44,12 @@ class Base(TxBase):
# given absolute fee in ETH, return gas price in ETH
def fee_abs2gasprice(self, abs_fee):
return self.proto.coin_amt(int(abs_fee.toWei() // self.gas.toWei()), from_unit='wei')
return self.proto.coin_amt(int(abs_fee.toWei() // self.gas), from_unit='wei')
# 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 self.proto.coin_amt(rel_fee * self.gas.toWei(), from_unit='wei')
return self.proto.coin_amt(rel_fee * self.gas, from_unit='wei')
def is_replaceable(self):
return True

View file

@ -16,6 +16,7 @@ from ....tx.info import TxInfo
from ....util import fmt, pp_fmt
from ....color import yellow, blue, cyan, pink
from ....addr import MMGenID
from ....obj import Int
class TxInfo(TxInfo):
txinfo_hdr_fs = '{hdr}\n ID={i} ({a} {c}) Sig={s} Locktime={l}\n'
@ -56,7 +57,7 @@ class TxInfo(TxInfo):
m = pink(tx.swap_memo) if tx.is_swap else None,
c = tx.proto.dcoin if len(tx.outputs) else '',
g = yellow(tx.pretty_fmt_fee(t['gasPrice'].to_unit('Gwei'))),
G = yellow(tx.pretty_fmt_fee(t['startGas'].to_unit('Kwei'))),
G = Int(t['startGas']).hl(),
f_mmid = mmid_disp(tx.inputs[0]),
t_mmid = mmid_disp(tx.outputs[0]) if tx.outputs and not tx.is_swap else '') + '\n\n'

View file

@ -35,10 +35,7 @@ class New(Base, TxBase.New):
super().__init__(*args, **kwargs)
if self.cfg.gas:
self.gas = self.proto.coin_amt(int(self.cfg.gas), from_unit='wei')
else:
self.gas = self.proto.coin_amt(self.dfl_gas, from_unit='wei')
self.gas = int(self.cfg.gas or self.dfl_gas)
if self.cfg.contract_data:
m = "'--contract-data' option may not be used with token transaction"
@ -82,12 +79,12 @@ class New(Base, TxBase.New):
def set_gas_with_data(self, data):
if not self.is_token:
self.gas = self.proto.coin_amt(self.dfl_gas + self.byte_cost * len(data), from_unit='wei')
self.gas = self.dfl_gas + self.byte_cost * len(data)
# one-shot method
def adj_gas_with_extra_data_len(self, extra_data_len):
if not (self.is_token or hasattr(self, '_gas_adjusted')):
self.gas += self.proto.coin_amt(self.byte_cost * extra_data_len, from_unit='wei')
self.gas += self.byte_cost * extra_data_len
self._gas_adjusted = True
async def process_cmdline_args(self, cmd_args, ad_f, ad_w):
@ -154,7 +151,7 @@ class New(Base, TxBase.New):
# given rel fee and units, return absolute fee using self.gas
def fee_rel2abs(self, tx_size, amt_in_units, unit):
return self.proto.coin_amt(int(amt_in_units * self.gas.toWei()), from_unit=unit)
return self.proto.coin_amt(int(amt_in_units * self.gas), from_unit=unit)
# given fee estimate (gas price) in wei, return absolute fee, adjusting by self.cfg.fee_adjust
def fee_est2abs(self, net_fee):

View file

@ -35,7 +35,7 @@ class Signed(Completed, TxBase.Signed):
'to': CoinAddr(self.proto, d['to']) if d['to'] else None,
'amt': self.proto.coin_amt(d['value'], from_unit='wei'),
'gasPrice': self.proto.coin_amt(d['gasprice'], from_unit='wei'),
'startGas': self.proto.coin_amt(d['startgas'], from_unit='wei'),
'startGas': d['startgas'],
'nonce': ETHNonce(d['nonce']),
'data': HexStr(d['data']) }
if o['data'] and not o['to']: # token- or contract-creating transaction

View file

@ -32,7 +32,9 @@ class Unsigned(Completed, TxBase.Unsigned):
'to': CoinAddr(self.proto, d['to']) if d['to'] else None,
'amt': self.proto.coin_amt(d['amt']),
'gasPrice': self.proto.coin_amt(d['gasPrice']),
'startGas': self.proto.coin_amt(d['startGas']),
'startGas': (
self.proto.coin_amt(d['startGas']).toWei() if '.' in d['startGas'] # for backward compat
else int(d['startGas'])),
'nonce': ETHNonce(d['nonce']),
'chainId': None if d['chainId'] == 'None' else Int(d['chainId']),
'data': HexStr(d['data'])}
@ -43,7 +45,7 @@ class Unsigned(Completed, TxBase.Unsigned):
async def do_sign(self, o, wif):
o_conv = {
'to': bytes.fromhex(o['to'] or ''),
'startgas': o['startGas'].toWei(),
'startgas': o['startGas'],
'gasprice': o['gasPrice'].toWei(),
'value': o['amt'].toWei() if o['amt'] else 0,
'nonce': o['nonce'],
@ -129,7 +131,7 @@ class TokenUnsigned(TokenCompleted, Unsigned):
self.swap_memo.encode(),
o['expiry'])
tx_in = c.make_tx_in(
gas = self.gas * (7.8 if self.cfg.test_suite else 2),
gas = self.gas * (7 if self.cfg.test_suite else 2),
gasPrice = o['gasPrice'],
nonce = o['nonce'] + 1,
data = cdata)

View file

@ -340,7 +340,7 @@ class CmdTestEthdevMethods:
to_addr = usr_addrs[i],
amt = amt,
key = dfl_devkey,
gas = self.proto.coin_amt(120000, from_unit='wei'),
gas = 120000,
gasPrice = self.proto.coin_amt(8, from_unit='Gwei'))
rpc = await self.rpc
for n in range(50): # long delay for txbump

View file

@ -83,14 +83,15 @@ class CmdTestEthSwapMethods:
def token_fund_user(self):
return self._token_transfer_ops(
op = 'fund_user',
mm_idxs = [1],
mm_idxs = [1, 2, 12],
token_addr = 'token_addr1',
amt = self.token_fund_amt)
def token_addrgen(self):
return self._token_addrgen(mm_idxs=[1], naddrs=5)
return self._token_addrgen(mm_idxs=[1], naddrs=12)
def token_addrimport(self):
return self._token_addrimport('token_addr1', '1-5', expect='5/5')
return self._token_addrimport('token_addr1', '1-12', expect='12/12')
def token_addrimport_inbound(self):
token_addr = self.read_from_tmpfile('token_addr1').strip()
@ -176,9 +177,10 @@ class CmdTestEthSwap(CmdTestSwapMethods, CmdTestRegtest):
),
'eth_fund': (
'funding the ETH tracking wallet',
('eth_fund_mmgen_addr1', ''),
('eth_fund_mmgen_addr2', ''),
('eth_bal1', ''),
('eth_fund_mmgen_addr1', ''),
('eth_fund_mmgen_addr1b', ''),
('eth_fund_mmgen_addr2', ''),
('eth_bal1', ''),
),
'token_init': (
'deploying tokens and initializing the ETH token tracking wallet',
@ -227,7 +229,8 @@ class CmdTestEthSwap(CmdTestSwapMethods, CmdTestRegtest):
'eth_token_swap': (
'swap operations (ETH -> ERC20, ERC20 -> BTC, ERC20 -> ETH)',
# ETH -> MM1
('eth_swaptxcreate3', ''),
('eth_swaptxcreate3a', ''),
('eth_swaptxcreate3b', ''),
('eth_swaptxsign3', ''),
('eth_swaptxsend3', ''),
('eth_swaptxmemo3', ''),
@ -240,7 +243,8 @@ class CmdTestEthSwap(CmdTestSwapMethods, CmdTestRegtest):
('eth_swaptxreceipt4', ''),
('eth_token_bal2', ''),
# MM1 -> ETH
('eth_swaptxcreate5', ''),
('eth_swaptxcreate5a', ''),
('eth_swaptxcreate5b', ''),
('eth_swaptxsign5', ''),
('eth_etherscan_server_start', ''),
('eth_swaptxsend5_test', ''),
@ -343,6 +347,7 @@ class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev
cmd_group_in = CmdTestEthdev.cmd_group_in + (
# eth_fund:
('fund_mmgen_addr1', 'funding user address :1)'),
('fund_mmgen_addr1b', 'funding user address :3)'),
('fund_mmgen_addr2', 'funding user address :11)'),
('bal1', 'the ETH balance'),
# eth_swap:
@ -367,7 +372,8 @@ class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev
# eth_token_swap:
# ETH -> MM1
('swaptxcreate3', 'creating an ETH->MM1 swap transaction'),
('swaptxcreate3a', 'creating an ETH->MM1 swap transaction'),
('swaptxcreate3b', 'creating an ETH->MM1 swap transaction (specific address)'),
('swaptxsign3', 'signing the transaction'),
('swaptxsend3', 'sending the transaction'),
('swaptxmemo3', 'the memo of the sent transaction'),
@ -382,7 +388,8 @@ class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev
('token_bal2', 'the token balance'),
# MM1 -> ETH
('swaptxcreate5', 'creating an MM1->ETH swap transaction'),
('swaptxcreate5a', 'creating an MM1->ETH swap transaction'),
('swaptxcreate5b', 'creating an MM1->ETH swap transaction (specific address)'),
('swaptxsign5', 'signing the transaction'),
('etherscan_server_start', 'starting the Etherscan server'),
('swaptxsend5_test', 'testing the transaction via Etherscan'),
@ -392,6 +399,9 @@ class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev
('etherscan_server_stop', 'stopping the Etherscan server'),
)
def fund_mmgen_addr1b(self):
return self._fund_mmgen_addr(arg=f'{dfl_sid}:E:3,0.001')
def swaptxcreate1(self):
t = self._swaptxcreate(['ETH', '8.765', 'BTC'])
t.expect('OK? (Y/n): ', 'y')
@ -404,7 +414,13 @@ class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev
add_opts = ['--trade-limit=3%']),
expect = ':2019e4/1/0')
def swaptxcreate3(self):
def swaptxcreate3a(self):
t = self._swaptxcreate(['ETH', '0.7654321', 'ETH.MM1'])
t.expect(f'{dfl_sid}:E:4') # check that correct unused address was found
t.expect('(Y/n): ', 'y')
return self._swaptxcreate_ui_common(t)
def swaptxcreate3b(self):
t = self._swaptxcreate(['ETH', '8.765', 'ETH.MM1', f'{dfl_sid}:E:5'])
return self._swaptxcreate_ui_common(t)
@ -424,7 +440,13 @@ class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev
t = self._swaptxcreate(['ETH.MM1', '87.654321', 'BTC', f'{dfl_sid}:C:2'])
return self._swaptxcreate_ui_common(t)
def swaptxcreate5(self):
def swaptxcreate5a(self):
t = self._swaptxcreate(['ETH.MM1', '98.7654321', 'ETH'])
t.expect(f'{dfl_sid}:E:13') # check that correct unused address was found
t.expect('(Y/n): ', 'y')
return self._swaptxcreate_ui_common(t)
def swaptxcreate5b(self):
t = self._swaptxcreate(['ETH.MM1', '98.7654321', 'ETH', f'{dfl_sid}:E:12'])
return self._swaptxcreate_ui_common(t)