Working with Keys
A private key
Every chain uses the same generator. You get 32 bytes of randomness as a 64 character hex string, nothing more.
import { useBlockchain } from "@agntn/keys";
import Bitcoin from "@agntn/keys/blockchains/bitcoin";
const chain = useBlockchain(new Bitcoin());
const privateKey = chain.generateKeyPrivate();
console.log(privateKey); // '7f9e5b9e3bbed34a4c28c8c1665525fc2cd7afb4fdc7edca3eb93ddf8a31ef56'
secp256k1 chains ask @noble/curves for a key that is guaranteed to sit inside the curve order. ed25519 chains take raw bytes from crypto.getRandomValues, because any 32 bytes are a valid ed25519 seed. Both work in Node and in the browser, which is what the Keyspace explorer relies on.
The public key
const publicKey = chain.getKeyPublic(privateKey);
console.log(publicKey); // '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc'
On secp256k1 chains this is the compressed form: 33 bytes, starting with 02 or 03. That is what Bitcoin, Ethereum, and TRON expect today. If you need the uncompressed 65 byte key, ask for it:
const uncompressed = chain.getKeyPublic(privateKey, { compressed: false });
// '04a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc7513...'
ed25519 chains have no compression flag. The public key is always 32 bytes.
Both at once
const keyPair = chain.generateKeys();
keyPair.keys.private;
keyPair.keys.public;
The same options apply, so chain.generateKeys({ compressed: false }) gives you an uncompressed pair.
The shape you get back
interface Keys {
keys: {
private: string;
public: string;
};
}
Hex strings everywhere. Sizes by curve:
| Curve | Private | Public |
|---|---|---|
| secp256k1 | 64 hex chars | 66 hex chars compressed, 130 uncompressed |
| ed25519 | 64 hex chars | 64 hex chars |
Sui speaks two curves
Sui accepts ed25519 and secp256k1 keys on the same chain. The private key is the same 32 bytes either way. The scheme option decides which curve turns it into a public key:
import Sui from "@agntn/keys/blockchains/sui";
const suiChain = useBlockchain(new Sui());
const ed25519PublicKey = suiChain.getKeyPublic(privateKey); // default
const secp256k1PublicKey = suiChain.getKeyPublic(privateKey, { scheme: "secp256k1" });
Pick the scheme once and carry it through to getAddress, otherwise the address will not match the key. The Sui page shows the full round trip.
Under the hood
Curves come from @noble/curves, hashes from @noble/hashes. There is no second crypto implementation anywhere in the package, and adding one is the first thing a review would reject. EVM chains share everything through AbstractEVMBlockchain, so Ethereum and Base are the same code with a different name and coin type.