I am trying to have the functionality provided by the Derive API locally in javascript. I have written a script and its working but its not giving the correct account_identifier. Below is the script, can someone help me here
the correct principal is dgsc3-x3mgj-35squ-7s7wl-ww65m-o55e2-xikdq-47ri3-27upl-b52sv-kqe
the correct account_id is 5b8ba540ea14bcf4f71a03cecbca0f3c8f15959beaad48a704470f1bb1f79ae7
import elliptic from 'elliptic';
import crypto from 'crypto';
import crc32 from 'crc-32';
import { Principal } from '@dfinity/principal';
const EC = new elliptic.ec('secp256k1');
const PrincipalIdClass = {
SelfAuthenticating: 0x01,
Opaque: 0x02,
Derived: 0x03,
Anonymous: 0x04,
};
class PrincipalId {
constructor(bytes) {
this.bytes = bytes;
}
static newSelfAuthenticating(publicKey) {
const sha224 = crypto.createHash('sha224');
sha224.update(publicKey);
const hash = sha224.digest();
const id = Buffer.concat([hash, Buffer.from([PrincipalIdClass.SelfAuthenticating])]);
return new PrincipalId(id);
}
}
function principalIdFromPublicKey(pkHex) {
const publicKeyBuffer = Buffer.from(pkHex, 'hex');
try {
const key = EC.keyFromPublic(publicKeyBuffer);
const sec1PublicKey = key.getPublic(true, 'hex');
const principalId = PrincipalId.newSelfAuthenticating(Buffer.from(sec1PublicKey, 'hex'));
const principal = Principal.fromUint8Array(principalId.bytes);
return { principalId, principal };
} catch (err) {
throw new Error(`Error processing public key: ${err.message}`);
}
}
function generateAccountIdentifier(principal, subAccount = new Uint8Array(32)) {
const ACCOUNT_DOMAIN_SEPARATOR = new Uint8Array([0x0A, ...Buffer.from('account-id')]);
const principalBytes = principal.toUint8Array();
const combinedBytes = new Uint8Array(
ACCOUNT_DOMAIN_SEPARATOR.length + principalBytes.length + subAccount.length
);
combinedBytes.set(ACCOUNT_DOMAIN_SEPARATOR, 0);
combinedBytes.set(principalBytes, ACCOUNT_DOMAIN_SEPARATOR.length);
combinedBytes.set(subAccount, ACCOUNT_DOMAIN_SEPARATOR.length + principalBytes.length);
const sha224Hash = crypto.createHash('sha224').update(combinedBytes).digest();
const checksum = Buffer.alloc(4);
checksum.writeUInt32BE(crc32.buf(sha224Hash) >>> 0, 0);
const accountIdBytes = Buffer.concat([checksum, sha224Hash]);
return accountIdBytes.toString('hex');
}
const pkHex = '047a83e378053f87b49aeae53b3ed274c8b2ffbe59d9a51e3c4d850ca8ac1684f7131b778317c0db04de661c7d08321d60c0507868af41fe3150d21b3c6c757367'; // Replace with actual hex public key
try {
const { principalId, principal } = principalIdFromPublicKey(pkHex);
console.log('Generated Principal ID:', principalId.bytes.toString('hex'));
console.log('Generated Principal:', principal);
const subAccount = new Uint8Array(32);
const accountId = generateAccountIdentifier(principal, subAccount);
console.log('Generated Account Identifier:', accountId);
} catch (error) {
console.error('Error:', error.message);
}