@chorus-one/signer-local
Version:
Local signer for Chorus One SDK that utilizes a BIP39 mnemonic for signing operations
130 lines (129 loc) • 5.29 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.LocalSigner = void 0;
const signer_1 = require("@chorus-one/signer");
const utils_1 = require("@chorus-one/utils");
const bip39_1 = require("bip39");
const ed25519_1 = require("./ed25519");
const secp256k1_1 = require("./secp256k1");
/**
* The LocalSigner in the Chorus One SDK is a specialized implementation of the Signer interface that utilizes a `BIP39`
* mnemonic for signing operations.
*
* This signer is ideal for local environments where you need a straightforward and
* secure method to generate and manage cryptographic keys from mnemonic phrases.
*/
class LocalSigner {
config;
accounts;
addressDerivationFn;
mnemonicToSeedFn;
seedToKeypairFn;
logger;
/**
* Constructs a new LocalSigner.
*
* @param params - The parameters required to initialize the LocalSigner
* @param params.mnemonic - A string containing your `BIP39` mnemonic phrase
* @param params.keyType - An enum specifying the signing key type (e.g. SECP256K1, ED25519)
* @param params.accounts - An array of account objects, each containing an HD path
* @param params.addressDerivationFn - A function that derives the address from the public key
* @param params.logger - (Optional) A logger to use for logging messages, i.e `console`
*
* @returns A new instance of LocalSigner.
*/
constructor(params) {
const { addressDerivationFn, ...config } = params;
this.config = config;
this.accounts = new Map();
this.logger = params.logger ?? utils_1.nopLogger;
this.addressDerivationFn = addressDerivationFn;
this.mnemonicToSeedFn = params.mnemonicToSeedFn ?? bip39_1.mnemonicToSeed;
this.seedToKeypairFn = params.seedToKeypairFn;
}
/**
* Initializes the signer, performing any necessary setup or configuration.
* @returns A promise that resolves once the initialization is complete.
*/
async init() {
const seed = await this.mnemonicToSeedFn(this.config.mnemonic);
await Promise.all(this.config.accounts.map(async (account) => {
let key;
switch (this.config.keyType) {
case undefined:
case signer_1.KeyType.SECP256K1: {
const fn = this.seedToKeypairFn ?? secp256k1_1.deriveKey;
key = await fn(seed, account.hdPath);
break;
}
case signer_1.KeyType.ED25519: {
const fn = this.seedToKeypairFn ?? ed25519_1.deriveKey;
key = await fn(seed, account.hdPath);
break;
}
default:
throw new Error('unsupported key type');
}
const publicKey = key.publicKey;
const privateKey = key.privateKey;
const derivedAddresses = await this.addressDerivationFn(key.publicKey, account.hdPath);
derivedAddresses.forEach((address) => {
this.accounts.set(address.toLowerCase(), {
hdPath: account.hdPath,
privateKey,
publicKey
});
});
}));
}
/**
* Signs the provided data using the private key associated with the signer's address.
*
* @param signerAddress - The address of the signer
* @param signerData - The data to be signed, which can be a raw message or custom data
*
* @returns A promise that resolves to an object containing the signature and public key.
*/
async sign(signerAddress, signerData) {
this.logger.info(`signing data from address: ${signerAddress}`);
if (signerData.message === undefined) {
throw new Error('missing message to sign');
}
const content = signerData.message;
let sig;
switch (this.config.keyType) {
case undefined:
case signer_1.KeyType.SECP256K1:
sig = await (0, secp256k1_1.sign)(content, this.getPrivateKey(signerAddress));
break;
case signer_1.KeyType.ED25519:
sig = await (0, ed25519_1.sign)(content, this.getPrivateKey(signerAddress));
break;
default:
throw new Error('unsupported key type');
}
return { sig, pk: await this.getPublicKey(signerAddress) };
}
/**
* Retrieves the public key associated with the signer's address.
*
* @param address - The address of the signer
*
* @returns A promise that resolves to a Uint8Array representing the public key.
*/
async getPublicKey(address) {
const account = this.accounts.get(address.toLowerCase());
if (account === undefined) {
throw new Error(`no public key found for address: ${address}`);
}
return account.publicKey;
}
getPrivateKey(address) {
const account = this.accounts.get(address.toLowerCase());
if (account === undefined) {
throw new Error(`no private key found for address: ${address}`);
}
return account.privateKey;
}
}
exports.LocalSigner = LocalSigner;