are there any methods or tools?
such as parachain id is 1000.
how to get this parachain's sovereignAccount
UPDATE: shawn's utils website has a "Para ID" to Address utility.
Here is parachain sovereign account 2000 (the AcountId32):
0x70617261 + d0070000 + 000000000000000000000000000000000000000000000000
0x70617261 = b"para" (up/down) or 0x7369626c = b"sibl" (side-to-side)
d0070000 = scale encoded number 2000
You can see the scale encoding of a u32 by typing the number into collatorSelection/setDesiredCandidates and looking at the encoded call details on the bottom right by max
that is the encoded version of 2000.
To copy and paste:
1000: 0x70617261e8030000000000000000000000000000000000000000000000000000
2000: 0x70617261d0070000000000000000000000000000000000000000000000000000
2001: 0x70617261d1070000000000000000000000000000000000000000000000000000
2002: 0x70617261d2070000000000000000000000000000000000000000000000000000
(That's also enough examples that you could guess the rest. I do think that we need an easy way to get these from polkadot-js maybe from the parachain screen? - PRs welcome!)
If you want a normal polkadot/kusama address then you can use the "AccountId to Hex" at https://www.shawntabrizi.com/substrate-js-utilities/ - paste in the above on the right hand side as the hex and you will get the address calculated. For example, for 1000 parachain id it returns 5Ec4AhPZk8STuex8Wsi9TwDtJQxKqzPJRCH7348Xtcs9vZLJ
subkey inspect
allows to get the public account in different formats
Commented
Jun 13, 2022 at 18:30
Id
(aka ParaId
) implements into_account_id()
, as described here. The code translates to ("para", id).encode()
, then decoded as a 32 byte account id, with trailing zeros if need be.
I am not aware of any tools, but probably it would be very easy to make one, or manually check them.
Now, we have another choice Subalfred
, a CLI toolbox.
# Sovereign address on relaychain.
subalfred key --type parachain 2000
public-key 0x70617261d0070000000000000000000000000000000000000000000000000000 ParaId(2000)
Substrate 5Ec4AhPUwPeyTFyuhGuBbD224mY85LKLMSqSSo33JYWCazU4
# Sovereign address on sibling chain.
subalfred key --type sibling 2000
public-key 0x7369626cd0070000000000000000000000000000000000000000000000000000 SiblId(2000)
Substrate 5Eg2fntJ27qsari4FGrGhrMqKFDRnkNSR6UshkZYBGXmSuC8
# Note that, if you are on Moonbeam-link chain, remove 24 trailing zeros from the public-key.
public-key 0x7369626cd0070000000000000000000000000000000000000000000000000000 SiblId(2000)
public-key 0x7369626cd0070000000000000000000000000000 SiblId(2000)
# Subalfred will detect if this is a sovereign address automatically.
subalfred key 5Eg2fntJ27qsari4FGrGhrMqKFDRnkNSR6UshkZYBGXmSuC8
public-key 0x7369626cd0070000000000000000000000000000000000000000000000000000 SiblId(2000)
Substrate 5Eg2fntJ27qsari4FGrGhrMqKFDRnkNSR6UshkZYBGXmSuC8
For more details, check the https://subalfred.hack.ink/user/cli/key.html.
The answers above are brilliant, but just in case is useful for other devs I want to share a code snippet to calculate the Sovereign Account in Rust.
use scale::Encode;
use sp_core::{crypto::{Ss58AddressFormatRegistry, Ss58Codec}, sr25519::Pair};
use sp_runtime::{MultiSigner};
let sovereign_account_str = calculate_sovereign_account::<Pair>(para_id)?;
fn calculate_sovereign_account<Pair>(
para_id: u32,
) -> Result<String, Box<dyn std::error::Error>>
where
Pair: sp_core::Pair,
Pair::Public: Into<MultiSigner>,
{
// Scale encoded para_id
let id = RococoId(para_id);
let encoded_id = hex::encode(id.encode());
// Prefix para or sibl
let prefix = hex::encode("para");
// Join both strings and the 0x at the beginning
let encoded_key = "0x".to_owned() + &prefix + &encoded_id;
// Fill the rest with 0s
let public_str = format!("{:0<width$}", encoded_key, width = 64 + 2);
// Convert hex public key to ss58 address
let public = array_bytes::hex2bytes(&public_str).expect("Failed to convert hex to bytes");
let public_key = Pair::Public::try_from(&public)
.map_err(|_| "Failed to construct public key from given hex")?;
Ok(public_key.to_ss58check_with_version(Ss58AddressFormatRegistry::SubstrateAccount.into()))
}
Using python's scalecodec
(py-scale-codec), you can get it like:
from scalecodec.base import ScaleBytes
from scalecodec.types import U32
from scalecodec.utils.ss58 import ss58_encode
def get_parachain_sovereign_account(para_id, chain_type='para'):
scale_encoded = chain_type.encode().hex()
scale_encoded += U32(ScaleBytes(bytearray())).encode(para_id).to_hex()[2:]
public_key = f"0x{scale_encoded + ''.join(['0' * (64 - len(scale_encoded))])}"
print(
f'\t Account ID:\t{public_key}\n' + \
f'\tSS58 Address:\t{ss58_encode(public_key)}'
)
Then...
get_parachain_sovereign_account(1000)
>>>
Account ID: 0x70617261e8030000000000000000000000000000000000000000000000000000
SS58 Address: 5Ec4AhPZk8STuex8Wsi9TwDtJQxKqzPJRCH7348Xtcs9vZLJ
get_parachain_sovereign_account(2000)
>>>
Account ID: 0x70617261d0070000000000000000000000000000000000000000000000000000
SS58 Address: 5Ec4AhPUwPeyTFyuhGuBbD224mY85LKLMSqSSo33JYWCazU4