Skip to content

v5 Migration Guide

Version 5 represents a major architectural overhaul of AlgoKit Utils for Python. The library has been decoupled from py-algorand-sdk (algosdk) and restructured into a multi-module package with custom-generated API clients. This enables:

  • No algosdk dependency — The library now uses generated clients and first-party transaction primitives instead of algosdk
  • Unified AlgorandClient — Still the single entry point for all Algorand interactions
  • Type-safe generated clients — Algod, Indexer, and KMD clients are generated from OpenAPI specs with full typing
  • Cross-SDK alignment — Naming conventions aligned with algokit-utils-ts for consistency across the Algorand SDK ecosystem

This guide covers both developers migrating their applications and the specific changes needed at each layer of the API.

Who is this for? If you are using algokit-utils v4 (including any legacy v2 APIs still available in v4), this guide will walk you through every breaking change.


v4v5Notes
AlgorandClient.default_localnet()AlgorandClient.default_localnet()Unchanged
AlgorandClient.testnet()AlgorandClient.testnet()Unchanged
AlgorandClient.mainnet()AlgorandClient.mainnet()Unchanged
AlgorandClient.from_environment()AlgorandClient.from_environment()Unchanged
get_algod_client()Removed — use AlgorandClient.*Legacy function deleted
get_indexer_client()Removed — use AlgorandClient.*Legacy function deleted
Operationv4 (legacy)v4 (modern) / v5
Paymenttransfer(TransferParameters(...))algorand.send.payment(PaymentParams(...))
Asset transfertransfer_asset(TransferAssetParameters(...))algorand.send.asset_transfer(AssetTransferParams(...))
Asset opt-inopt_in(algod, account, asset_id)algorand.send.asset_opt_in(AssetOptInParams(...))
Ensure fundedensure_funded(EnsureBalanceParameters(...))algorand.account.ensure_funded(addr, dispenser, amount)
App deployapp_client.deploy(...)app_factory.deploy(...)
App callApplicationClient.call(...)app_client.send.call(...)
v4v5Notes
SigningAccountAddressWithSigners.address.addr
TransactionSignerAccountProtocolAddressWithTransactionSigner.address.addr
MultisigMetadata.addressesMultisigMetadata.addrsField renamed
MultiSigAccountMultisigAccountClass renamed
SendAtomicTransactionComposerResultsSendTransactionComposerResultsClass renamed
SourceMapProgramSourceMapClass renamed
OnComplete.NoOpOCOnApplicationComplete.NoOpEnum renamed
populate_app_call_resourcespopulate_group_resourcesFunction renamed

v4 was a single algokit_utils package that depended on py-algorand-sdk. v5 bundles 8 top-level Python modules into a single algokit-utils distribution:

ModulePurposeReplaces
algokit_utilsHigh-level orchestration (AlgorandClient, AppClient, etc.)Slimmed down from v4
algokit_transactTransaction building, signing, encodingalgosdk.transaction, algosdk.atomic_transaction_composer
algokit_algod_clientTyped Algod REST client (OAS-generated)algosdk.v2client.algod.AlgodClient
algokit_indexer_clientTyped Indexer REST client (OAS-generated)algosdk.v2client.indexer.IndexerClient
algokit_kmd_clientTyped KMD REST client (OAS-generated)algosdk.kmd.KMDClient
algokit_abiABI encoding/decoding, ARC-32/ARC-56 app specsalgosdk.abi + custom ARC code
algokit_algo25Mnemonic/key generation (25-word scheme)algosdk.mnemonic
algokit_commonShared primitives (address, hashing, constants)Various algosdk internals

All 8 modules install together via pip install algokit-utils. You can import directly from any module:

# High-level (most common)
from algokit_utils import AlgorandClient, AppClient, PaymentParams
# Or import from specific modules
from algokit_transact import Transaction, TransactionType, OnApplicationComplete
from algokit_algod_client import AlgodClient
from algokit_abi.arc56 import Arc56Contract
from algokit_algo25 import mnemonic_from_seed

The project build system has changed from Poetry to uv:

  • poetry.lockuv.lock
  • Build backend: poetry-coreuv_build

If you are contributing to algokit-utils-py, you’ll need to install uv instead of Poetry.

Removed:

  • py-algorand-sdk (algosdk) — completely removed

Added:

  • httpx — HTTP client for generated API clients
  • msgpack / msgpack-types — MessagePack encoding (previously via algosdk)
  • pynacl — Ed25519 signing (previously via algosdk)
  • pycryptodomex — Cryptographic operations (previously via algosdk)

If your code imports from algosdk directly, you will need to replace all those imports with the equivalent algokit_* module.

What you needv4 importv5 import
Algod clientfrom algosdk.v2client.algod import AlgodClientfrom algokit_algod_client import AlgodClient
Indexer clientfrom algosdk.v2client.indexer import IndexerClientfrom algokit_indexer_client import IndexerClient
KMD clientfrom algosdk.kmd import KMDClientfrom algokit_kmd_client import KmdClient
Transaction typesfrom algosdk.transaction import PaymentTxnfrom algokit_transact import Transaction, PaymentTransactionFields
Transaction signerfrom algosdk.atomic_transaction_composer import TransactionSignerfrom algokit_transact import TransactionSigner
OnCompletefrom algosdk.transaction import OnCompletefrom algokit_transact import OnApplicationComplete
Mnemonicsfrom algosdk import mnemonicfrom algokit_algo25 import mnemonic_from_seed, seed_from_mnemonic
ABI typesfrom algosdk.abi import ABITypefrom algokit_abi.abi import ...
ARC-56 specfrom algokit_utils.applications.app_spec.arc56 import Arc56Contractfrom algokit_abi.arc56 import Arc56Contract
ARC-32 specfrom algokit_utils.applications.app_spec.arc32 import Arc32Contractfrom algokit_abi.arc32 import Arc32Contract
Address utilitiesfrom algosdk import encodingfrom algokit_common import address_from_public_key, public_key_from_address
Constantsfrom algosdk import constantsfrom algokit_common import MIN_TXN_FEE, ZERO_ADDRESS
Source mapfrom algosdk.source_map import SourceMapfrom algokit_common import ProgramSourceMap

You can also access most transaction types via the algokit_utils.transact facade:

# These are equivalent:
from algokit_transact import Transaction, OnApplicationComplete
from algokit_utils.transact import Transaction, OnApplicationComplete

AlgorandClient remains the primary entry point. Its public API is largely unchanged:

from algokit_utils import AlgorandClient
# These all work the same as v4
algorand = AlgorandClient.default_localnet()
algorand = AlgorandClient.testnet()
algorand = AlgorandClient.mainnet()
algorand = AlgorandClient.from_environment()

The internal client types have changed (see below), but if you only interact through AlgorandClient, most of your code should continue to work.

The underlying client types are now generated from OpenAPI specs instead of coming from algosdk:

# v4
from algosdk.v2client.algod import AlgodClient
from algosdk.v2client.indexer import IndexerClient
from algosdk.kmd import KMDClient
# v5
from algokit_algod_client import AlgodClient
from algokit_indexer_client import IndexerClient
from algokit_kmd_client import KmdClient # Note: lowercase 'md'

If you access raw clients via algorand.client.algod, the returned type is now algokit_algod_client.AlgodClient instead of algosdk.v2client.algod.AlgodClient. Update any type annotations accordingly.

Client configuration types are now per-package:

# v4
from algokit_utils.models.network import AlgoClientNetworkConfig
# v5 — AlgoClientNetworkConfig still works, but underlying clients use:
from algokit_algod_client import ClientConfig as AlgodClientConfig
from algokit_indexer_client import ClientConfig as IndexerClientConfig
from algokit_kmd_client import ClientConfig as KmdClientConfig

The SuggestedParams type now comes from the generated Algod client with different field names:

# v4 (algosdk)
params.gen # genesis ID
params.gh # genesis hash
# v5 (algokit_algod_client)
params.genesis_id # genesis ID
params.genesis_hash # genesis hash

v5 adds a close() method to ClientManager for properly closing HTTP connections (the generated clients use httpx):

algorand = AlgorandClient.default_localnet()
# ... use the client ...
algorand.client.close() # Clean up HTTP connections

The primary account type has been replaced with a secretless signing architecture. SigningAccount stored the raw private key as a field (account.private_key). AddressWithSigners never exposes the key — it is held in closures, enabling KMS/HSM compatibility:

# v4
from algokit_utils import SigningAccount
account = SigningAccount(private_key=key)
print(account.address) # string address
print(account.private_key) # raw key was readable
# v5
from algokit_transact import AddressWithSigners
# Or generate via AlgorandClient (recommended)
account = algorand.account.random()
print(account.addr) # .address → .addr
# account.private_key does not exist — key is in a signing closure

Note: There is no backward-compatible alias for SigningAccount. All usages must be updated.

If you have existing code that holds a raw base64 private key string (e.g. loaded from environment or storage), use make_basic_account_transaction_signer as the bridge:

from algokit_transact import make_basic_account_transaction_signer
from algokit_common import address_from_public_key
import base64
# Bridge for legacy raw-key code
signer = make_basic_account_transaction_signer(private_key_b64)
# Or create a full AddressWithSigners from an existing key:
from algokit_transact import generate_address_with_signers
import nacl.signing
key_bytes = base64.b64decode(private_key_b64)
seed = key_bytes[:32]
public_key = key_bytes[32:]
signing_key = nacl.signing.SigningKey(seed)
account = generate_address_with_signers(
ed25519_pubkey=public_key,
raw_ed25519_signer=lambda data: signing_key.sign(data).signature,
)

3.2 TransactionSignerAccountProtocol → AddressWithTransactionSigner

Section titled “3.2 TransactionSignerAccountProtocol → AddressWithTransactionSigner”
# v4
from algokit_utils import TransactionSignerAccountProtocol
def my_function(account: TransactionSignerAccountProtocol):
print(account.address)
# v5
from algokit_transact import AddressWithTransactionSigner
def my_function(account: AddressWithTransactionSigner):
print(account.addr) # .address → .addr

3.3 MultisigAccount/MultisigMetadata Relocation and Renames

Section titled “3.3 MultisigAccount/MultisigMetadata Relocation and Renames”

These types have moved to algokit_transact with naming changes:

# v4
from algokit_utils.models.account import MultiSigAccount, MultisigMetadata
metadata = MultisigMetadata(version=1, threshold=2, addresses=["addr1", "addr2"])
msig = MultiSigAccount(metadata, [signer1, signer2])
# v5
from algokit_transact import MultisigAccount, MultisigMetadata
metadata = MultisigMetadata(version=1, threshold=2, addrs=["addr1", "addr2"]) # .addresses → .addrs
msig = MultisigAccount(metadata, [signer1, signer2]) # MultiSigAccount → MultisigAccount

Backward-compatible re-exports for MultisigAccount, MultisigMetadata, and LogicSigAccount exist via algokit_utils.transact and algokit_utils.models.account. Note that SigningAccount has no compat re-export — see 3.1.

# v4
from algokit_utils.models.account import LogicSigAccount
# v5
from algokit_transact import LogicSigAccount
# Or via AlgorandClient
lsig_account = algorand.account.logicsig(program)

v5 introduces a richer signer hierarchy from algokit_transact:

TypePurpose
TransactionSignerSigns transactions (callable protocol, no longer ABC)
BytesSignerSigns raw bytes
ProgramDataSignerSigns program data
MxBytesSignerSigns MX-prefixed bytes
DelegatedLsigSignerCreates delegated logic signatures
AddressWithSignersAddress + all signer types bundled together

The OnComplete enum from algosdk is replaced by OnApplicationComplete from algokit_transact:

# v4
from algosdk.transaction import OnComplete
on_complete = OnComplete.NoOpOC
on_complete = OnComplete.OptInOC
on_complete = OnComplete.CloseOutOC
on_complete = OnComplete.ClearStateOC
on_complete = OnComplete.UpdateApplicationOC
on_complete = OnComplete.DeleteApplicationOC
# v5
from algokit_transact import OnApplicationComplete
on_complete = OnApplicationComplete.NoOp
on_complete = OnApplicationComplete.OptIn
on_complete = OnApplicationComplete.CloseOut
on_complete = OnApplicationComplete.ClearState
on_complete = OnApplicationComplete.UpdateApplication
on_complete = OnApplicationComplete.DeleteApplication

The TransactionSigner is now a callable protocol instead of an abstract base class:

# v4
from algosdk.atomic_transaction_composer import TransactionSigner # ABC with .sign_transactions()
# v5
from algokit_transact import TransactionSigner # Callable protocol

The TransactionComposer constructor now takes a TransactionComposerParams dataclass:

# v4
composer = TransactionComposer(
algod=algod_client,
get_signer=get_signer_fn,
get_suggested_params=get_params_fn,
)
# v5
from algokit_utils.transactions import TransactionComposer, TransactionComposerParams
composer = TransactionComposer(
params=TransactionComposerParams(
algod=algod_client,
get_signer=get_signer_fn,
get_suggested_params=get_params_fn,
)
)

Composer-level fee and resource behaviour is controlled via the separate TransactionComposerConfig dataclass, passed as composer_config inside TransactionComposerParams:

from algokit_utils.transactions import TransactionComposer, TransactionComposerParams, TransactionComposerConfig
composer = TransactionComposer(
params=TransactionComposerParams(
algod=algod_client,
get_signer=get_signer_fn,
composer_config=TransactionComposerConfig(
cover_app_call_inner_transaction_fees=True, # default: False
populate_app_call_resources=False, # default: True
),
)
)

Result types have been renamed:

# v4
from algokit_utils import SendAtomicTransactionComposerResults
# v5
from algokit_utils import SendTransactionComposerResults

Transaction parameter dataclasses have moved to algokit_utils.transactions.types:

from algokit_utils import (
PaymentParams,
AssetCreateParams,
AssetTransferParams,
AssetOptInParams,
AssetOptOutParams,
AppCallParams,
AppCreateParams,
AppUpdateParams,
AppDeleteParams,
OnlineKeyRegistrationParams,
OfflineKeyRegistrationParams,
)

The types themselves (PaymentParams, AppCallParams, etc.) keep the same names and fields.

v5 adds a transactions/builders/ package with functions for constructing low-level algokit_transact.Transaction objects:

from algokit_utils.transactions.builders import (
build_payment_transaction,
build_app_call_transaction,
build_app_create_transaction,
build_asset_create_transaction,
build_asset_transfer_transaction,
build_asset_opt_in_transaction,
# ... etc.
)

These are useful when you need fine-grained control over transaction construction at the algokit_transact level.

# v4
from algokit_utils import populate_app_call_resources
# v5
from algokit_utils.transactions.composer_resources import (
populate_group_resources,
populate_transaction_resources,
)

The helper functions prepare_group_for_sending and send_atomic_transaction_composer have been removed from the public API.

New types for fee management:

from algokit_utils.transactions.fee_coverage import FeeDeltaType, FeeDelta, FeePriority

FeeDeltaType is an enum discriminant on FeeDelta.delta_type indicating whether the fee delta is a fixed amount or a multiplier. FeePriority configures priority fee strategies.


Part 5: App Client and Smart Contract Changes

Section titled “Part 5: App Client and Smart Contract Changes”

The old ApplicationClient class from _legacy_v2 has been completely removed:

# v4 (legacy)
from algokit_utils import ApplicationClient
app_client = ApplicationClient(algod_client, app_spec, sender=account)
result = app_client.call("hello", name="world")
# v5 — use AppClient and AppFactory instead
from algokit_utils import AlgorandClient
algorand = AlgorandClient.default_localnet()
# For deploying new apps, use AppFactory
factory = algorand.client.get_app_factory(app_spec=arc56_spec, default_sender=sender)
app_client, result = factory.deploy(...)
# For interacting with existing apps, use AppClient
app_client = algorand.client.get_app_client_by_id(app_spec=arc56_spec, app_id=app_id, default_sender=sender)
result = app_client.send.call(method="hello", args=["world"])

The old ApplicationSpecification class is no longer accepted:

# v4
from algokit_utils import ApplicationSpecification
spec = ApplicationSpecification(...)
# v5 — use Arc56Contract (ARC-32 specs are auto-converted)
from algokit_abi.arc56 import Arc56Contract
from algokit_abi.arc32 import Arc32Contract

get_app_factory() and get_app_client_by_id() now only accept Arc56Contract | str, not ApplicationSpecification.

ARC-32 and ARC-56 contract specifications have moved to the algokit_abi package:

# v4
from algokit_utils.applications.app_spec.arc56 import Arc56Contract
from algokit_utils.applications.app_spec.arc32 import Arc32Contract
# v5
from algokit_abi.arc56 import Arc56Contract
from algokit_abi.arc32 import Arc32Contract
# Still re-exported for convenience:
from algokit_utils.applications.app_spec import Arc56Contract, Arc32Contract

Transaction confirmation results are now typed objects instead of dictionaries:

# v4 — dict-style access
result = algorand.send.payment(PaymentParams(...))
app_id = result.confirmation["application-index"]
asset_id = result.confirmation["asset-index"]
# v5 — typed attribute access
result = algorand.send.payment(PaymentParams(...))
app_id = result.confirmation.app_id
asset_id = result.confirmation.asset_id

The confirmation field is now algod_models.PendingTransactionResponse (a typed dataclass) instead of AlgodResponseType (a dict-like object).


⚠️ Silent runtime risk: These type changes do not produce ImportError or AttributeError at startup — they will only fail at runtime when your code processes the return value. Make sure to test all ABI method call paths, not just import paths.

ABI decoding now returns more Pythonic types:

ABI Typev4 returnsv5 returns
byte, byte[], byte[n]list[int]bytes
ufixed<N>x<M>intdecimal.Decimal
Tuple types (e.g., (uint64,address))listtuple

If your code processes ABI return values, update type expectations:

# v4
result = app_client.call("get_bytes")
byte_list: list[int] = result.return_value # [72, 101, 108, 108, 111]
# v5
result = app_client.send.call(method="get_bytes")
byte_data: bytes = result.abi_return.return_value # b"Hello"
ABI Typev4 acceptsv5 accepts
byteintbytes or int
ufixed<N>x<M>intdecimal.Decimal or int

Block models from the generated Algod client have been reorganized:

# v4
from algokit_algod_client.models import GetBlock
response: GetBlock = algod_client.get_block(...)
fee_sink = response.block.header.fee_sink
protocol = response.block.header.current_protocol
proposal = response.block.header.upgrade_propose
tx_root = response.block.header.transactions_root
# v5
from algokit_algod_client.models import BlockResponse
response: BlockResponse = algod_client.get_block(...)
fee_sink = response.block.header.reward_state.fee_sink
protocol = response.block.header.upgrade_state.current_protocol
proposal = response.block.header.upgrade_vote.upgrade_propose
tx_root = response.block.header.txn_commitments.transactions_root

Header fields have been reorganized into nested types:

  • Reward fields → header.reward_state.*
  • Protocol fields → header.upgrade_state.*
  • Upgrade vote fields → header.upgrade_vote.*
  • Transaction root fields → header.txn_commitments.*

Other changes:

  • BlockEvalDelta.bytesBlockEvalDelta.bytes_value (avoids Python keyword conflict)
  • previous_block_hash and genesis_hash are now non-optional with bytes(32) defaults

v5 enforces runtime validation for fixed-length byte fields (32 and 64 bytes). Fields that previously accepted any length now raise ValueError:

# v4 — silently accepted wrong lengths
txn.group = bytes(10) # No error
# v5 — raises ValueError
txn.group = bytes(10) # ValueError: Expected 32 bytes, got 10
txn.group = bytes(32) # OK

Affected fields: group, lease, transaction hashes, block hashes, keys (32 bytes), signatures, SHA-512 hashes (64 bytes).

Response types from the generated Algod client are now proper typed dataclasses. If you were accessing responses as dictionaries (e.g., response["key"]), switch to attribute access (e.g., response.key).


The algokit_common module provides constants and functions that were previously scattered across algosdk:

from algokit_common import (
# Constants
ADDRESS_LENGTH,
CHECKSUM_BYTE_LENGTH,
HASH_BYTES_LENGTH,
MAX_TRANSACTION_GROUP_SIZE,
MICROALGOS_TO_ALGOS_RATIO,
MIN_TXN_FEE,
PUBLIC_KEY_BYTE_LENGTH,
SIGNATURE_BYTE_LENGTH,
TRANSACTION_ID_LENGTH,
ZERO_ADDRESS,
# Functions
address_from_public_key,
get_application_address,
public_key_from_address,
sha512_256,
# Source map
ProgramSourceMap,
)

These are also accessible via algokit_utils.common.

# v4
from algosdk.source_map import SourceMap
# v5
from algokit_common import ProgramSourceMap

AlgoAmount now supports full comparison operations and accepts int in arithmetic:

from algokit_utils import AlgoAmount
a = AlgoAmount.from_algo(5)
b = AlgoAmount.from_algo(3)
# New in v5: full comparison support
assert a > b
assert a >= b
assert b < a
# New in v5: arithmetic with int (treated as micro-algos)
result = a + 1_000_000 # adds 1 Algo worth of micro-algos
result = a - 500_000

Mnemonic operations are now in the algokit_algo25 package:

# v4
from algosdk import mnemonic
words = mnemonic.from_private_key(private_key)
key = mnemonic.to_private_key(words)
# v5
from algokit_algo25 import (
mnemonic_from_seed,
seed_from_mnemonic,
secret_key_to_mnemonic,
master_derivation_key_to_mnemonic,
mnemonic_to_master_derivation_key,
)
words = secret_key_to_mnemonic(secret_key)
seed = seed_from_mnemonic(words)

Also accessible via algokit_utils.algo25.


Removed Functionv5 Replacement
get_algod_client()AlgorandClient.default_localnet() / .testnet() / .mainnet()
get_indexer_client()Access via algorand.client.indexer
get_kmd_client_from_algod_client()Access via algorand.client.kmd
get_account()algorand.account.from_environment(name)
get_account_from_mnemonic()algorand.account.from_mnemonic(mnemonic)
get_localnet_default_account()algorand.account.localnet_dispenser()
get_dispenser_account()algorand.account.dispenser_from_environment()
create_kmd_wallet_account()algorand.account.from_kmd(...)
get_or_create_kmd_wallet_account()algorand.account.from_kmd(...)
get_kmd_wallet_account()algorand.account.from_kmd(...)
ensure_funded()algorand.account.ensure_funded(addr, dispenser, amount)
transfer()algorand.send.payment(PaymentParams(...))
transfer_asset()algorand.send.asset_transfer(AssetTransferParams(...))
opt_in()algorand.send.asset_opt_in(AssetOptInParams(...))
opt_out()algorand.send.asset_opt_out(AssetOptOutParams(...))
is_localnet()algorand.client.network returns NetworkDetail
is_mainnet()algorand.client.network.is_mainnet
is_testnet()algorand.client.network.is_testnet
execute_atc_with_logic_error()Use TransactionComposer directly
get_next_version()Internal to deploy logic
get_sender_from_signer()No longer needed
num_extra_program_pages()calculate_extra_program_pages() in transactions/helpers.py
replace_template_variables()Internal to deploy logic
get_app_id_from_tx_id()Access result.app_id from send result
get_creator_apps()Use AppDeployer directly
Removed Classv5 Replacement
ApplicationClientAppClient / AppFactory via algorand.client.get_app_client_by_id() / get_app_factory()
ApplicationSpecificationArc56Contract from algokit_abi
Account (NamedTuple)AddressWithSigners from algokit_transact
ProgramCompile via AppClient or AppManager
AlgoClientConfigAlgoClientNetworkConfig
ABITransactionResponseTyped result objects from .send.*() calls
CommonCallParameters / CommonCallParametersDictCommonTxnParams
CreateCallParameters / CreateCallParametersDictAppCreateParams
TransactionParameters / TransactionParametersDictSpecific param types (PaymentParams, etc.)
OnCompleteCallParametersAppCallParams with on_complete field
EnsureBalanceParametersalgorand.account.ensure_funded() params
EnsureFundedResponseTyped result from ensure_funded()
TransferParametersPaymentParams
TransferAssetParametersAssetTransferParams
AppDeployMetaData / AppMetaData / AppLookup / AppReferenceInternal to AppDeployer
DeployResponse / DeploymentFailedErrorResult types from AppFactory.deploy()
ABICallArgs / DeployCallArgs / DeployCreateCallArgsMethod call params in AppFactory
MethodHints / MethodConfigDict / CallConfigARC-56 natively handles these
TemplateValueDict / TemplateValueMappingdeploy_time_params in AppFactory

The algokit_utils.beta package (which contained deprecation-warning shims for account_manager, algorand_client, client_manager, composer) is removed. Import directly from algokit_utils instead:

# v4 (beta imports — deprecated)
from algokit_utils.beta.algorand_client import AlgorandClient
from algokit_utils.beta.account_manager import AccountManager
from algokit_utils.beta.composer import TransactionComposer
# v5 (direct imports)
from algokit_utils import AlgorandClient
from algokit_utils.accounts import AccountManager
from algokit_utils.transactions import TransactionComposer

These files that re-exported legacy v2 code with deprecation warnings are deleted:

  • algokit_utils.account
  • algokit_utils.application_client
  • algokit_utils.application_specification
  • algokit_utils.asset
  • algokit_utils.deploy
  • algokit_utils.dispenser_api
  • algokit_utils.logic_error
  • algokit_utils.network_clients

Terminal window
# Remove algosdk from your dependencies
pip uninstall py-algorand-sdk
# Install the latest algokit-utils (v5 includes all sub-packages)
pip install --upgrade algokit-utils
  • If using get_algod_client() / get_indexer_client(), replace with AlgorandClient.*
  • If already using AlgorandClient, no changes needed
  • Replace all from algosdk imports with equivalent algokit_* imports (see 1.4)
  • Replace from algokit_utils._legacy_v2 imports
  • Replace from algokit_utils.beta imports
  • Update Arc56Contract / Arc32Contract imports to algokit_abi
  • SigningAccountAddressWithSigners
  • .address.addr on all account/signer types
  • TransactionSignerAccountProtocolAddressWithTransactionSigner
  • MultiSigAccountMultisigAccount
  • MultisigMetadata.addresses.addrs
  • OnComplete.NoOpOCOnApplicationComplete.NoOp (and similar)
  • SendAtomicTransactionComposerResultsSendTransactionComposerResults
  • populate_app_call_resourcespopulate_group_resources
  • Update TransactionComposer constructor if using directly
  • Replace ApplicationClient with AppClient / AppFactory
  • Replace ApplicationSpecification with Arc56Contract
  • Update method call patterns to use app_client.send.call(...) interface
  • Update code expecting list[int] from byte types — now returns bytes
  • Update code expecting int from ufixed types — now returns decimal.Decimal
  • Update code expecting list from tuple types — now returns tuple
  • Replace algosdk.v2client.algod.AlgodClient type annotations with algokit_algod_client.AlgodClient
  • Replace algosdk.v2client.indexer.IndexerClient with algokit_indexer_client.IndexerClient
  • Replace algosdk.kmd.KMDClient with algokit_kmd_client.KmdClient
  • Update SuggestedParams field access: .gen.genesis_id, .gh.genesis_hash
  • Replace algosdk.source_map.SourceMap with algokit_common.ProgramSourceMap
  • Replace dict-style confirmation access (["application-index"]) with attribute access (.app_id)
  • Replace dict-style confirmation access (["asset-index"]) with attribute access (.asset_id)
  • Update block model access for nested header fields (see 7.1)
  • Run your test suite
  • Check for ImportError / ModuleNotFoundError (indicates missed import updates)
  • Check for AttributeError on .address (should be .addr)
  • Check for TypeError on ABI return values (type changes)
  • Test transaction signing and sending end-to-end