@jagad/icsi
Version:
Internet Computer Subaccount Indexer Library - TypeScript SDK for ICP multi-token subaccount management, transaction tracking, and automated sweeping with webhook support
161 lines (160 loc) • 7.14 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getIdentityFromPrivateKey = exports.getIdentityFromSeed = void 0;
exports.isNotEmptyOrError = isNotEmptyOrError;
exports.createHostAgentAndIdentityFromSeed = createHostAgentAndIdentityFromSeed;
exports.createHostAgentAndIdentityFromPrivateKey = createHostAgentAndIdentityFromPrivateKey;
const cross_fetch_1 = __importDefault(require("cross-fetch"));
const agent_1 = require("@dfinity/agent");
const bip39 = __importStar(require("bip39"));
const hdkey_1 = __importDefault(require("hdkey"));
const secp256k1_1 = require("secp256k1");
const identity_secp256k1_1 = require("@dfinity/identity-secp256k1");
// Define the BIP44 derivation path for ICP.
const DERIVATION_PATH = "m/44'/223'/0'/0";
/**
* Checks if a value is not empty or throws an error.
* @param value - The value to check.
* @param errorMessage - The error message to throw if the value is empty.
* @throws {Error} - Throws an error with the specified message if the value is empty.
*/
function isNotEmptyOrError(variable, message = undefined) {
let error_msg;
if (message === undefined) {
error_msg = 'Variable is empty.';
}
else {
error_msg = message;
}
if (Array.isArray(variable)) {
if (variable.length < 1) {
throw new Error(error_msg);
}
}
else {
if (variable === undefined || variable === '' || variable === null) {
throw new Error(error_msg);
}
}
}
/**
* Generates a Secp256k1KeyIdentity from a seed phrase and an optional index.
* @param {string} mnemonic - The mnemonic seed phrase.
* @param {number} [index=0] - The index to use in the derivation path (default is 0).
* @returns {Secp256k1KeyIdentity} - The generated Secp256k1KeyIdentity.
*/
const getIdentityFromSeed = (mnemonic, index = 0) => {
if (!mnemonic || mnemonic.trim() === '') {
throw new Error('Mnemonic seed phrase cannot be empty');
}
if (!bip39.validateMnemonic(mnemonic)) {
throw new Error('Invalid mnemonic seed phrase');
}
const seed = bip39.mnemonicToSeedSync(mnemonic);
const masterKey = hdkey_1.default.fromMasterSeed(seed);
// Derive the private and public keys using the BIP44 derivation path.
const { privateKey } = masterKey.derive(`${DERIVATION_PATH}/${index}`);
const publicKey = (0, secp256k1_1.publicKeyCreate)(privateKey, false);
return identity_secp256k1_1.Secp256k1KeyIdentity.fromKeyPair(publicKey, privateKey);
};
exports.getIdentityFromSeed = getIdentityFromSeed;
/**
* Generates a Secp256k1KeyIdentity from a private key in various formats.
* @param {string} privateKey - The private key as hex string or EC PEM format.
* @returns {Secp256k1KeyIdentity} - The generated Secp256k1KeyIdentity.
*/
const getIdentityFromPrivateKey = (privateKey) => {
if (!privateKey || typeof privateKey !== 'string') {
throw new Error('Private key cannot be empty');
}
try {
// Check if it's a PEM format
if (privateKey.includes('-----BEGIN') && privateKey.includes('-----END')) {
// For PEM format, try to parse using the Secp256k1KeyIdentity.fromPem method
try {
return identity_secp256k1_1.Secp256k1KeyIdentity.fromPem(privateKey);
}
catch (pemError) {
throw new Error(`Failed to parse PEM private key: ${pemError.message}. Make sure it's a valid EC (secp256k1) private key in PEM format.`);
}
}
// Handle hex format (with or without 0x prefix)
const cleanPrivateKey = privateKey.replace(/^0x/, '').replace(/\s/g, '');
if (cleanPrivateKey.length !== 64) {
throw new Error('Private key must be 64 hex characters (32 bytes) for secp256k1');
}
const privateKeyBuffer = Buffer.from(cleanPrivateKey, 'hex');
const publicKey = (0, secp256k1_1.publicKeyCreate)(privateKeyBuffer, false);
return identity_secp256k1_1.Secp256k1KeyIdentity.fromKeyPair(publicKey, privateKeyBuffer);
}
catch (error) {
throw new Error(`Invalid private key format: ${error.message}`);
}
};
exports.getIdentityFromPrivateKey = getIdentityFromPrivateKey;
/**
* Creates an HttpAgent with a Secp256k1KeyIdentity from a given seed phrase.
* @param {string} seedPhrase - The seed phrase to generate the identity.
* @param {string} [host="https://ic0.app"] - The host URL for the HttpAgent (default is the IC mainnet URL).
* @returns {HttpAgent} - The initialized HttpAgent with the generated identity.
*/
function createHostAgentAndIdentityFromSeed(seedPhrase, host = 'https://ic0.app') {
const identity = (0, exports.getIdentityFromSeed)(seedPhrase);
// Initialize and return the HttpAgent with the generated identity.
return new agent_1.HttpAgent({
host,
identity,
fetch: cross_fetch_1.default,
});
}
/**
* Creates an HttpAgent with a Secp256k1KeyIdentity from a private key.
* @param {string} privateKey - The private key in EC PEM format or as a hex string.
* @param {string} [host="https://ic0.app"] - The host URL for the HttpAgent (default is the IC mainnet URL).
* @returns {HttpAgent} - The initialized HttpAgent with the generated identity.
*/
function createHostAgentAndIdentityFromPrivateKey(privateKey, host = 'https://ic0.app') {
const identity = (0, exports.getIdentityFromPrivateKey)(privateKey);
// Initialize and return the HttpAgent with the generated identity.
return new agent_1.HttpAgent({
host,
identity,
fetch: cross_fetch_1.default,
});
}