mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-23 06:48:16 +00:00
trezorctl: support sending ERC20 tokens in ethereum-sign-tx
This commit is contained in:
parent
3997b402b4
commit
1e9edf0cc5
65
trezorctl
65
trezorctl
@ -1220,8 +1220,27 @@ def ethereum_list_units(ctx, param, value):
|
|||||||
ctx.exit()
|
ctx.exit()
|
||||||
|
|
||||||
|
|
||||||
|
def ethereum_erc20_contract(w3, token_address, to_address, amount):
|
||||||
|
min_abi = [
|
||||||
|
{
|
||||||
|
"name": "transfer",
|
||||||
|
"type": "function",
|
||||||
|
"constant": False,
|
||||||
|
"inputs": [
|
||||||
|
{"name": "_to", "type": "address"},
|
||||||
|
{"name": "_value", "type": "uint256"},
|
||||||
|
],
|
||||||
|
"outputs": [{"name": "", "type": "bool"}],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
contract = w3.eth.contract(address=token_address, abi=min_abi)
|
||||||
|
return contract.encodeABI("transfer", [to_address, amount])
|
||||||
|
|
||||||
|
|
||||||
@cli.command()
|
@cli.command()
|
||||||
@click.option("-c", "--chain-id", type=int, help="EIP-155 chain id (replay protection)")
|
@click.option(
|
||||||
|
"-c", "--chain-id", type=int, default=1, help="EIP-155 chain id (replay protection)"
|
||||||
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"-n",
|
"-n",
|
||||||
"--address",
|
"--address",
|
||||||
@ -1240,9 +1259,10 @@ def ethereum_list_units(ctx, param, value):
|
|||||||
@click.option(
|
@click.option(
|
||||||
"-i", "--nonce", type=int, help="Transaction counter (required for offline signing)"
|
"-i", "--nonce", type=int, help="Transaction counter (required for offline signing)"
|
||||||
)
|
)
|
||||||
@click.option("-d", "--data", default="", help="Data as hex string, e.g. 0x12345678")
|
@click.option("-d", "--data", help="Data as hex string, e.g. 0x12345678")
|
||||||
@click.option("-p", "--publish", is_flag=True, help="Publish transaction via RPC")
|
@click.option("-p", "--publish", is_flag=True, help="Publish transaction via RPC")
|
||||||
@click.option("-x", "--tx-type", type=int, help="TX type (used only for Wanchain)")
|
@click.option("-x", "--tx-type", type=int, help="TX type (used only for Wanchain)")
|
||||||
|
@click.option("-t", "--token", help="ERC20 token address")
|
||||||
@click.option(
|
@click.option(
|
||||||
"--list-units",
|
"--list-units",
|
||||||
is_flag=True,
|
is_flag=True,
|
||||||
@ -1251,7 +1271,7 @@ def ethereum_list_units(ctx, param, value):
|
|||||||
callback=ethereum_list_units,
|
callback=ethereum_list_units,
|
||||||
expose_value=False,
|
expose_value=False,
|
||||||
)
|
)
|
||||||
@click.argument("to")
|
@click.argument("to_address")
|
||||||
@click.argument("amount", callback=ethereum_amount_to_int)
|
@click.argument("amount", callback=ethereum_amount_to_int)
|
||||||
@click.pass_obj
|
@click.pass_obj
|
||||||
def ethereum_sign_tx(
|
def ethereum_sign_tx(
|
||||||
@ -1264,25 +1284,21 @@ def ethereum_sign_tx(
|
|||||||
nonce,
|
nonce,
|
||||||
data,
|
data,
|
||||||
publish,
|
publish,
|
||||||
to,
|
to_address,
|
||||||
tx_type,
|
tx_type,
|
||||||
|
token,
|
||||||
):
|
):
|
||||||
"""Sign (and optionally publish) Ethereum transaction.
|
"""Sign (and optionally publish) Ethereum transaction.
|
||||||
|
|
||||||
Use TO as destination address, or set TO to "" for contract creation.
|
Use TO_ADDRESS as destination address, or set to "" for contract creation.
|
||||||
|
|
||||||
|
Specify a contract address with the --token option to send an ERC20 token.
|
||||||
|
|
||||||
You can specify AMOUNT and gas price either as a number of wei,
|
You can specify AMOUNT and gas price either as a number of wei,
|
||||||
or you can use a unit suffix.
|
or you can use a unit suffix.
|
||||||
E.g., the following are equivalent:
|
|
||||||
|
|
||||||
\b
|
|
||||||
0.000314eth
|
|
||||||
0.314milliether
|
|
||||||
314000000nano
|
|
||||||
314000000000000wei
|
|
||||||
314000000000000
|
|
||||||
|
|
||||||
Use the --list-units option to show all known currency units.
|
Use the --list-units option to show all known currency units.
|
||||||
|
ERC20 token amounts are specified in eth/wei, custom units are not supported.
|
||||||
|
|
||||||
If any of gas price, gas limit and nonce is not specified, this command will
|
If any of gas price, gas limit and nonce is not specified, this command will
|
||||||
try to connect to an ethereum node and auto-fill these values. You can configure
|
try to connect to an ethereum node and auto-fill these values. You can configure
|
||||||
@ -1295,9 +1311,10 @@ def ethereum_sign_tx(
|
|||||||
click.echo(" pip install web3 rlp")
|
click.echo(" pip install web3 rlp")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if gas_price is None or gas_limit is None or nonce is None or publish:
|
|
||||||
w3 = web3.Web3()
|
w3 = web3.Web3()
|
||||||
if not w3.isConnected():
|
if (
|
||||||
|
gas_price is None or gas_limit is None or nonce is None or publish
|
||||||
|
) and not w3.isConnected():
|
||||||
click.echo("Failed to connect to Ethereum node.")
|
click.echo("Failed to connect to Ethereum node.")
|
||||||
click.echo(
|
click.echo(
|
||||||
"If you want to sign offline, make sure you provide --gas-price, "
|
"If you want to sign offline, make sure you provide --gas-price, "
|
||||||
@ -1305,12 +1322,19 @@ def ethereum_sign_tx(
|
|||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
to_address = ethereum_decode_hex(to)
|
if data is not None and token is not None:
|
||||||
|
click.echo("Can't send tokens and custom data at the same time")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
client = connect()
|
client = connect()
|
||||||
address_n = tools.parse_path(address)
|
address_n = tools.parse_path(address)
|
||||||
from_address = ethereum.get_address(client, address_n)
|
from_address = ethereum.get_address(client, address_n)
|
||||||
|
|
||||||
|
if token:
|
||||||
|
data = ethereum_erc20_contract(w3, token, to_address, amount)
|
||||||
|
to_address = token
|
||||||
|
amount = 0
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
data = ethereum_decode_hex(data)
|
data = ethereum_decode_hex(data)
|
||||||
else:
|
else:
|
||||||
@ -1339,19 +1363,18 @@ def ethereum_sign_tx(
|
|||||||
nonce=nonce,
|
nonce=nonce,
|
||||||
gas_price=gas_price,
|
gas_price=gas_price,
|
||||||
gas_limit=gas_limit,
|
gas_limit=gas_limit,
|
||||||
to=to,
|
to=to_address,
|
||||||
value=amount,
|
value=amount,
|
||||||
data=data,
|
data=data,
|
||||||
chain_id=chain_id,
|
chain_id=chain_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
to = ethereum_decode_hex(to_address)
|
||||||
if tx_type is None:
|
if tx_type is None:
|
||||||
transaction = rlp.encode(
|
transaction = rlp.encode((nonce, gas_price, gas_limit, to, amount, data) + sig)
|
||||||
(nonce, gas_price, gas_limit, to_address, amount, data) + sig
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
transaction = rlp.encode(
|
transaction = rlp.encode(
|
||||||
(tx_type, nonce, gas_price, gas_limit, to_address, amount, data) + sig
|
(tx_type, nonce, gas_price, gas_limit, to, amount, data) + sig
|
||||||
)
|
)
|
||||||
tx_hex = "0x%s" % transaction.hex()
|
tx_hex = "0x%s" % transaction.hex()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user