Skip to content
This repository has been archived by the owner on Jun 6, 2024. It is now read-only.

Commit

Permalink
feat: export (#129)
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Jan 30, 2023
1 parent 6c54a3d commit 4b084c5
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
21 changes: 20 additions & 1 deletion ape_starknet/accounts/_cli.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
from typing import List, Optional, Union, cast

import click
Expand All @@ -6,7 +7,9 @@
from ape.cli.options import ApeCliContextObject
from ape.logging import logger
from ape.utils import add_padding_to_strings
from eth_utils import is_hex, to_hex
from eth_keyfile import decode_keyfile_json
from eth_utils import is_hex, text_if_str, to_bytes, to_hex
from hexbytes import HexBytes
from starkware.crypto.signature.signature import EC_ORDER
from starkware.starknet.definitions.fields import ContractAddressSalt

Expand Down Expand Up @@ -294,6 +297,22 @@ def _import(cli_ctx, alias, network, address, class_hash, salt):
cli_ctx.logger.success(f"Imported account '{alias}'.")


@accounts.command(short_help="Export an account private key")
@ape_cli_context()
@existing_alias_argument(account_type=StarknetKeyfileAccount)
def export(cli_ctx, alias):
account = cast(StarknetKeyfileAccount, _get_container(cli_ctx).load(alias))
path = account.key_file_path
account_json = json.loads(path.read_text())
passphrase = click.prompt("Enter password to decrypt account", hide_input=True)
passphrase_bytes = text_if_str(to_bytes, passphrase)
decoded_json = HexBytes(decode_keyfile_json(account_json, passphrase_bytes))
private_key = to_int(decoded_json.hex())
cli_ctx.logger.success(
f"Account {account.alias} private key: {click.style(private_key, bold=True)})"
)


@accounts.command()
@ape_cli_context()
@existing_alias_argument(account_type=BaseStarknetAccount)
Expand Down
18 changes: 18 additions & 0 deletions tests/integration/test_accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

import pytest
from eth_utils import to_hex
from starknet_py.utils.crypto.facade import message_signature
from starkware.crypto.signature.signature import EC_ORDER

from ape_starknet.types import StarknetSignableMessage
from ape_starknet.utils import get_random_private_key, to_int

from .conftest import ApeStarknetCliRunner
Expand Down Expand Up @@ -351,3 +353,19 @@ def test_change_password(accounts_runner, key_file_account, password, existing_k
assert "SUCCESS" in accounts_runner.invoke(
"change-password", existing_key_file_alias, input=[new_password, password, password]
)


def test_export(accounts_runner, key_file_account, password):
output = accounts_runner.invoke("export", key_file_account.alias, input=[password])
key_from_output = int(output.split(" private key: ")[-1].strip(" )\n"))

# Sign a message using the exported private key.
msg = StarknetSignableMessage(message="test test test")
actual_signature = message_signature(msg.hash, key_from_output)

# Sign the same message using the account.
with accounts_runner.runner.isolation(f"y\n{password}\n"):
expected_signature = key_file_account.sign_message(msg)

# The signatures should be the same to prove exporting works.
assert actual_signature == expected_signature

0 comments on commit 4b084c5

Please sign in to comment.