Skip to content

Commit

Permalink
Merge pull request #86 from inaie-makerx/fix-rekey-transfer
Browse files Browse the repository at this point in the history
fix: Fix problem with transfer from rekeyed account in wallet
  • Loading branch information
neilcampbell authored May 13, 2024
2 parents 5ee3a3b + 1504b00 commit 1fbf2d6
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 14 deletions.
2 changes: 1 addition & 1 deletion docs/html/searchindex.js

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 11 additions & 6 deletions src/algokit_utils/_transfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def transfer(client: "AlgodClient", parameters: TransferParameters) -> PaymentTx
params = parameters
params.suggested_params = parameters.suggested_params or client.suggested_params()
from_account = params.from_account
sender = address_from_private_key(from_account.private_key) # type: ignore[no-untyped-call]
sender = _get_address(from_account)
transaction = PaymentTxn(
sender=sender,
receiver=params.to_address,
Expand All @@ -105,7 +105,7 @@ def transfer_asset(client: "AlgodClient", parameters: TransferAssetParameters) -

params = parameters
params.suggested_params = parameters.suggested_params or client.suggested_params()
sender = address_from_private_key(parameters.from_account.private_key) # type: ignore[no-untyped-call]
sender = _get_address(parameters.from_account)
suggested_params = parameters.suggested_params or client.suggested_params()
xfer_txn = AssetTransferTxn(
sp=suggested_params,
Expand Down Expand Up @@ -139,9 +139,14 @@ def _send_transaction(
client.send_transaction(signed_transaction)

txid = transaction.get_txid() # type: ignore[no-untyped-call]
logger.debug(
f"Sent transaction {txid} type={transaction.type} from "
f"{address_from_private_key(parameters.from_account.private_key)}" # type: ignore[no-untyped-call]
)
logger.debug(f"Sent transaction {txid} type={transaction.type} from {_get_address(parameters.from_account)}")

return transaction


def _get_address(account: Account | AccountTransactionSigner) -> str:
if type(account) is Account:
return account.address
else:
address = address_from_private_key(account.private_key) # type: ignore[no-untyped-call]
return str(address)
87 changes: 87 additions & 0 deletions tests/test_transfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
)
from algokit_utils.dispenser_api import DispenserApiConfig
from algokit_utils.network_clients import get_algod_client, get_algonode_config
from algosdk.atomic_transaction_composer import AccountTransactionSigner
from algosdk.transaction import PaymentTxn
from algosdk.util import algos_to_microalgos
from pytest_httpx import HTTPXMock

Expand All @@ -38,6 +40,53 @@ def to_account(kmd_client: "KMDClient") -> Account:
return create_kmd_wallet_account(kmd_client, get_unique_name())


@pytest.fixture()
def rekeyed_from_account(algod_client: "AlgodClient", kmd_client: "KMDClient") -> Account:
account = create_kmd_wallet_account(kmd_client, get_unique_name())
rekey_account = create_kmd_wallet_account(kmd_client, get_unique_name())

ensure_funded(
algod_client,
EnsureBalanceParameters(
account_to_fund=account,
min_spending_balance_micro_algos=300000,
min_funding_increment_micro_algos=1,
),
)

rekey_txn = PaymentTxn(
sender=account.address,
receiver=account.address,
amt=0,
note="rekey account",
rekey_to=rekey_account.address,
sp=algod_client.suggested_params(),
) # type: ignore[no-untyped-call]
signed_rekey_txn = rekey_txn.sign(account.private_key) # type: ignore[no-untyped-call]
algod_client.send_transaction(signed_rekey_txn)

return Account(address=account.address, private_key=rekey_account.private_key)


@pytest.fixture()
def transaction_signer_from_account(
kmd_client: "KMDClient",
algod_client: "AlgodClient",
) -> AccountTransactionSigner:
account = create_kmd_wallet_account(kmd_client, get_unique_name())

ensure_funded(
algod_client,
EnsureBalanceParameters(
account_to_fund=account,
min_spending_balance_micro_algos=300000,
min_funding_increment_micro_algos=1,
),
)

return AccountTransactionSigner(private_key=account.private_key)


@pytest.fixture()
def clawback_account(kmd_client: "KMDClient") -> Account:
return create_kmd_wallet_account(kmd_client, get_unique_name())
Expand All @@ -60,6 +109,44 @@ def test_transfer_algo(algod_client: "AlgodClient", to_account: Account, funded_
assert actual_amount == requested_amount


def test_transfer_algo_rekey_account(
algod_client: "AlgodClient", to_account: Account, rekeyed_from_account: Account
) -> None:
requested_amount = 100_000
transfer(
algod_client,
TransferParameters(
from_account=rekeyed_from_account,
to_address=to_account.address,
micro_algos=requested_amount,
),
)

to_account_info = algod_client.account_info(to_account.address)
assert isinstance(to_account_info, dict)
actual_amount = to_account_info.get("amount")
assert actual_amount == requested_amount


def test_transfer_algo_transaction_signer_account(
algod_client: "AlgodClient", to_account: Account, transaction_signer_from_account: AccountTransactionSigner
) -> None:
requested_amount = 100_000
transfer(
algod_client,
TransferParameters(
from_account=transaction_signer_from_account,
to_address=to_account.address,
micro_algos=requested_amount,
),
)

to_account_info = algod_client.account_info(to_account.address)
assert isinstance(to_account_info, dict)
actual_amount = to_account_info.get("amount")
assert actual_amount == requested_amount


def test_transfer_algo_max_fee_fails(algod_client: "AlgodClient", to_account: Account, funded_account: Account) -> None:
requested_amount = 100_000
max_fee = 123
Expand Down

1 comment on commit 1fbf2d6

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/algokit_utils
   _debugging.py140795%20, 41, 76, 80, 89, 129, 157
   _ensure_funded.py69199%99
   _transfer.py67396%13, 76–77
   account.py851385%14–17, 61–65, 96, 109, 136, 139, 183
   application_client.py5337786%59–60, 166, 171, 200, 312, 317–318, 320, 322, 787, 802, 820–823, 913, 953, 965, 978, 1020, 1080–1086, 1090–1095, 1097, 1133, 1140, 1253, 1283, 1297, 1342–1344, 1346, 1356–1413, 1424–1429, 1449–1452
   application_specification.py971189%92, 94, 193–202, 206
   asset.py79594%9, 27–30
   common.py13192%13
   config.py511865%38–39, 50, 55, 60, 64–69, 100–109
   deploy.py4592495%31–34, 169, 173–174, 191, 206, 247, 403, 414–422, 439–442, 452, 460, 653–654, 678
   dispenser_api.py821285%112–113, 117–120, 155–157, 176–178
   logic_error.py38295%6, 29
   models.py227697%45, 50–52, 61–62
   network_clients.py74396%106–107, 138
src/algokit_utils/beta
   account_manager.py551475%39–40, 64, 123–130, 183–187, 198–200
   algorand_client.py1011585%111–112, 121–122, 143–145, 154–155, 224, 259, 274, 290, 303, 319
   client_manager.py371073%40, 61–63, 68–70, 75–78
   composer.py3207178%335–336, 339–340, 343–344, 347–348, 355–356, 359–360, 389, 391, 393, 396, 399, 404, 407, 411, 414, 456–489, 494–505, 510–516, 521–529, 549–562, 566, 590, 593–610, 618, 643, 659–660, 662–663, 665–666, 668–669, 671–672, 678–682
TOTAL254129388% 

Tests Skipped Failures Errors Time
205 0 💤 0 ❌ 0 🔥 2m 50s ⏱️

Please sign in to comment.