Cardano (ADA): Extended public key (xpub) doesn't bring all transactions
complete
M
Manual Panther
I am still having this same issue can someone look at my Cardano transactions?
M
Merlot Swift
updated the status to
complete
D
Dawn pink Narwhal
Merlot Swift: How was this fixed?
D
Dahlia Stork
Any idea when this would be done? I am getting wildly inaccurate results in the meantime so I really need this for my taxes.
D
Dahlia Stork
If you are using the Cardano Serialization Library (CSL) for address derivation (which is probable) then I just made this using the Bip32PublicKey class:
enum CardanoKeyRole {
External = 0,
Internal = 1,
Staking = 2,
}
export class XPubkey {
pubAccountKey: Bip32PublicKey
private constructor(pubKey: Bip32PublicKey) {
this.pubAccountKey = pubKey
}
static fromBech32(bech32: string): XPubkey {
return new XPubkey(Bip32PublicKey.from_bech32(bech32))
}
// bech32
pubKeyBech32 = () => this.pubAccountKey.to_bech32()
// external addresses
paymentKeyHash = (index: number = 0) => toHex(getStakeCredential(
this.pubAccountKey.derive(CardanoKeyRole.External).derive(index)
).to_bytes().slice(-28))
// internal addresses
changeKeyHash = (index: number = 0) => toHex(getStakeCredential(
this.pubAccountKey.derive(CardanoKeyRole.Internal).derive(index)
).to_bytes().slice(-28))
}
I just verified it against my wallet (Eternl) and it works for my pub key to generate all external and internal addresses
So you can do
const xpub = 'xpub1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
const key = XPubkey.fromBech32(xpub)
const i = 0; // address index
const externalAddressesHexa = key.paymentKeyHash(i)
const changelAddressesHexa = key.changeKeyHash(i)
Photo Viewer
View photos in a modal
D
Dahlia Stork
Using the headers of Cardano address
In hexadecimal, the "common" addresses out there have the header "61" (payment only) and "01" (payment + staking). The next 56 hexa letters (or 28 bytes) are the payment credentials that you can derive from the public key.
Sources:
Derivation of owned addresses
You have a public account key so the first three derivations are already done (m/1852'/1815'/account_number'/). What you derive are the PaymentKeyHash of the /0/x (external addresses) and /1/x (internal or change addresses).
Now, determining the amount of addresses to derive is tricky... People usually use a concept like -> look 10 (or 100) keys farther than the last used key... But be prepared to look into at least 512 for largish wallets. Or even further. I would always derive at least 256 of /0/x and /1/x and check for activity.
Cleverness at trying to identify single address wallets here could help with some optimization... Though we all know where that leads.
Staking addresses
Are NOT a solution for this. First of all, you can put any staking address unto whatever payment credentials (meaning you could wrongly identify tokens as belonging to the wrong person). And also people can use addresses with no staking address.
Implementation
I would definitely make a hashtable of the owned address to get an O(1) hit/miss lookup when trying to verify is an own address. Then, whenever you encounter an address in a transaction, you convert it to hexa, split the [2..57] letters of the payment key hash and look it up in the hashtable.
(Bonus points for checking the header byte for '01', '21', 41' and '61' to make sure you HAVE a PaymentKeyHash.)
This post was marked as
planned