p-sdk-wallet
Version:
A comprehensive wallet SDK for React Native (pwc), supporting multi-chain and multi-account features.
160 lines (159 loc) • 6.37 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;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.SolanaKeyring = void 0;
const web3_js_1 = require("@solana/web3.js");
const ed25519_hd_key_1 = require("ed25519-hd-key");
const bip39 = __importStar(require("bip39"));
const buffer_1 = require("buffer");
const chains_1 = require("../config/chains");
/**
* Solana keyring for managing multiple Solana accounts
* derived from a single mnemonic phrase using BIP-44 derivation paths.
* Supports Solana blockchain with Ed25519 keypairs.
*/
class SolanaKeyring {
/**
* Creates a new SolanaKeyring instance from a mnemonic phrase.
* @param mnemonic - The mnemonic phrase (12, 15, 18, 21, or 24 words)
* @throws Error if the mnemonic is invalid
*/
constructor(mnemonic) {
this.type = 'Solana';
this.keypairs = new Map();
this.accounts = [];
if (!bip39.validateMnemonic(mnemonic)) {
throw new Error('Invalid mnemonic');
}
this.mnemonic = mnemonic;
this.initializeFromMnemonic(mnemonic);
}
/**
* Initializes the keyring by generating the seed and creating the first account.
* @param mnemonic - The mnemonic phrase to initialize from
*/
initializeFromMnemonic(mnemonic) {
const seed = bip39.mnemonicToSeedSync(mnemonic);
const firstKeypair = this.deriveKeypair(seed, 0);
this.keypairs.set(firstKeypair.publicKey.toString(), firstKeypair);
this.accounts.push(firstKeypair.publicKey.toString());
}
/**
* Derives a Solana keypair at a specific index using BIP-44 derivation.
* @param seed - The seed buffer to derive from
* @param index - The account index to derive (0-based)
* @returns The derived Solana keypair
*/
deriveKeypair(seed, index) {
const path = `${chains_1.DERIVATION_PATHS.SOLANA.slice(0, -1)}${index}'`;
const derivedSeed = (0, ed25519_hd_key_1.derivePath)(path, seed.toString('hex')).key;
return web3_js_1.Keypair.fromSeed(derivedSeed);
}
/**
* Adds a new Solana account derived from the mnemonic at the next available index.
* @returns Promise resolving to the public key address of the newly created account
* @throws Error if account derivation fails or duplicate address is generated
*/
async addNewAccount() {
const newIndex = this.accounts.length;
const seed = bip39.mnemonicToSeedSync(this.mnemonic);
const newKeypair = this.deriveKeypair(seed, newIndex);
if (this.accounts.includes(newKeypair.publicKey.toString())) {
throw new Error('Duplicate account derived. Please check derivation path logic.');
}
this.keypairs.set(newKeypair.publicKey.toString(), newKeypair);
this.accounts.push(newKeypair.publicKey.toString());
return newKeypair.publicKey.toString();
}
/**
* Gets the private key for a given address managed by this keyring.
* @param address - The account's public key address to get the private key for
* @returns Promise resolving to the private key as a hex string
* @throws Error if the address is not found in this keyring
*/
async getPrivateKeyForAddress(address) {
const keypair = this.keypairs.get(address);
if (!keypair) {
throw new Error('Address not found in this keyring.');
}
return buffer_1.Buffer.from(keypair.secretKey).toString('hex');
}
/**
* Returns the mnemonic phrase. USE WITH CAUTION - this exposes sensitive data.
* @returns The mnemonic phrase as a string
*/
getMnemonic() {
return this.mnemonic;
}
/**
* Serializes the keyring data for encryption and storage.
* @returns An object containing the keyring type and mnemonic
*/
serialize() {
return {
type: this.type,
mnemonic: this.mnemonic
};
}
/**
* Deserializes data into a SolanaKeyring instance.
* @param data - The serialized keyring data
* @returns Promise resolving to a new SolanaKeyring instance
* @throws Error if the data is invalid or missing required fields
*/
static async deserialize(data) {
if (data.type !== 'Solana' || !data.mnemonic) {
throw new Error('Invalid data for SolanaKeyring deserialization.');
}
// Chỉ khôi phục mnemonic, không khôi phục lại accounts
return new SolanaKeyring(data.mnemonic);
}
/**
* Gets the Solana keypair for a given address.
* @param address - The account's public key address
* @returns The Solana keypair or undefined if not found
*/
getKeypair(address) {
return this.keypairs.get(address);
}
/**
* Gets all keypairs managed by this keyring.
* @returns Array of all Solana keypairs
*/
getAllKeypairs() {
return Array.from(this.keypairs.values());
}
}
exports.SolanaKeyring = SolanaKeyring;