Subxt has very basic support for turning 32-byte account IDs (aka public keys) into SS58 addresses. This is how:
use subxt::utils::AccountId32;
let account_id_bytes: [u8; 32] = // ...
let ss58_address = AccountId32::from(account_id_bytes).to_string();
SS58 addresses have the format <address-type> + <account-id> + <checksum>
, and Subxt always sets the address type to 42 (meaning "This is a generic substrate address and is valid on any chain"), and only supports SS58 encoding 32 byte account IDs.
If you'd like more control over how you build SS58 addresses (eg you want to set the address type to that for a specific chain), then you can also look at the sp-core
crate and (for 32 byte IDs) this function: https://docs.rs/sp-core/23.0.0/sp_core/crypto/struct.AccountId32.html#method.to_ss58check_with_version. With that you'd end up with code like:
use sp_core::crypto::{AccountId32,Ss58Codec,Ss58AddressFormat};
let account_id_bytes: [u8; 32] = // ...
let address_type: u16 = // ...
let ss58_address = AccountId32::from(account_id_bytes)
.to_ss58check_with_version(Ss58AddressFormat::custom(address_type));
Where address_type
is an ID for a particular chain. Some valid values for this can be found by looking at this enum: https://docs.rs/sp-core/23.0.0/sp_core/crypto/enum.Ss58AddressFormatRegistry.html, so eg for an address specific to an Astar account you could use:
let address_type = Ss58AddressFormatRegistry::AstarAccount as u16;