@thorwallet/xchain-ethereum
Version:
Ethereum client for XChainJS
184 lines • 8.37 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifyTypedData = exports.verifyMessage = exports.Wallet = void 0;
const tslib_1 = require("tslib");
const address_1 = require("@ethersproject/address");
const abstract_provider_1 = require("@ethersproject/abstract-provider");
const abstract_signer_1 = require("@ethersproject/abstract-signer");
const bytes_1 = require("@ethersproject/bytes");
const hash_1 = require("@ethersproject/hash");
const keccak256_1 = require("@ethersproject/keccak256");
const properties_1 = require("@ethersproject/properties");
const random_1 = require("@ethersproject/random");
const signing_key_1 = require("@ethersproject/signing-key");
const json_wallets_1 = require("@ethersproject/json-wallets");
const transactions_1 = require("@ethersproject/transactions");
const logger_1 = require("@ethersproject/logger");
const hdnode_1 = require("../hdnode/hdnode");
const logger = new logger_1.Logger('THORWALLET_ETHERS_WALLET');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isAccount(value) {
return value != null && bytes_1.isHexString(value.privateKey, 32) && value.address != null;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function hasMnemonic(value) {
const mnemonic = value.mnemonic;
return mnemonic && mnemonic.phrase;
}
class Wallet extends abstract_signer_1.Signer {
constructor(privateKey, provider) {
logger.checkNew(new.target, Wallet);
super();
if (isAccount(privateKey)) {
const signingKey = new signing_key_1.SigningKey(privateKey.privateKey);
properties_1.defineReadOnly(this, '_signingKey', () => signingKey);
properties_1.defineReadOnly(this, 'address', transactions_1.computeAddress(this.publicKey));
if (this.address !== address_1.getAddress(privateKey.address)) {
logger.throwArgumentError('privateKey/address mismatch', 'privateKey', '[REDACTED]');
}
if (hasMnemonic(privateKey)) {
const srcMnemonic = privateKey.mnemonic;
properties_1.defineReadOnly(this, '_mnemonic', () => ({
phrase: srcMnemonic.phrase,
path: srcMnemonic.path || hdnode_1.defaultPath,
locale: srcMnemonic.locale || 'en',
}));
}
else {
properties_1.defineReadOnly(this, '_mnemonic', () => null);
}
}
else {
if (signing_key_1.SigningKey.isSigningKey(privateKey)) {
/* istanbul ignore if */
if (privateKey.curve !== 'secp256k1') {
logger.throwArgumentError('unsupported curve; must be secp256k1', 'privateKey', '[REDACTED]');
}
properties_1.defineReadOnly(this, '_signingKey', () => privateKey);
}
else {
// A lot of common tools do not prefix private keys with a 0x (see: #1166)
if (typeof privateKey === 'string') {
if (privateKey.match(/^[0-9a-f]*$/i) && privateKey.length === 64) {
privateKey = '0x' + privateKey;
}
}
const signingKey = new signing_key_1.SigningKey(privateKey);
properties_1.defineReadOnly(this, '_signingKey', () => signingKey);
}
properties_1.defineReadOnly(this, '_mnemonic', () => null);
properties_1.defineReadOnly(this, 'address', transactions_1.computeAddress(this.publicKey));
}
/* istanbul ignore if */
if (provider && !abstract_provider_1.Provider.isProvider(provider)) {
logger.throwArgumentError('invalid provider', 'provider', provider);
}
properties_1.defineReadOnly(this, 'provider', provider || null);
}
get mnemonic() {
return this._mnemonic();
}
get privateKey() {
return this._signingKey().privateKey;
}
get publicKey() {
return this._signingKey().publicKey;
}
getAddress() {
return Promise.resolve(this.address);
}
connect(provider) {
return new Wallet(this, provider);
}
signTransaction(transaction) {
return properties_1.resolveProperties(transaction).then((tx) => {
if (tx.from != null) {
if (address_1.getAddress(tx.from) !== this.address) {
logger.throwArgumentError('transaction from address mismatch', 'transaction.from', transaction.from);
}
delete tx.from;
}
const signature = this._signingKey().signDigest(keccak256_1.keccak256(transactions_1.serialize(tx)));
return transactions_1.serialize(tx, signature);
});
}
signMessage(message) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
return bytes_1.joinSignature(this._signingKey().signDigest(hash_1.hashMessage(message)));
});
}
_signTypedData(domain, types, value) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
// Populate any ENS names
const populated = yield hash_1._TypedDataEncoder.resolveNames(domain, types, value, (name) => {
if (this.provider == null) {
logger.throwError('cannot resolve ENS names without a provider', logger_1.Logger.errors.UNSUPPORTED_OPERATION, {
operation: 'resolveName',
value: name,
});
}
return this.provider.resolveName(name);
});
return bytes_1.joinSignature(this._signingKey().signDigest(hash_1._TypedDataEncoder.hash(populated.domain, types, populated.value)));
});
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
encrypt(password, options, progressCallback) {
if (typeof options === 'function' && !progressCallback) {
progressCallback = options;
options = {};
}
if (progressCallback && typeof progressCallback !== 'function') {
throw new Error('invalid callback');
}
if (!options) {
options = {};
}
return json_wallets_1.encryptKeystore(this, password, options, progressCallback);
}
/**
* Static methods to create Wallet instances.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static createRandom(options) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
let entropy = random_1.randomBytes(16);
if (!options) {
options = {};
}
if (options.extraEntropy) {
entropy = bytes_1.arrayify(bytes_1.hexDataSlice(keccak256_1.keccak256(bytes_1.concat([entropy, options.extraEntropy])), 0, 16));
}
const mnemonic = yield hdnode_1.entropyToMnemonic(entropy, options.locale);
return Wallet.fromMnemonic(mnemonic, options.path, options.locale);
});
}
static fromEncryptedJson(json, password, progressCallback) {
return json_wallets_1.decryptJsonWallet(json, password, progressCallback).then((account) => {
return new Wallet(account);
});
}
static fromEncryptedJsonSync(json, password) {
return new Wallet(json_wallets_1.decryptJsonWalletSync(json, password));
}
static fromMnemonic(mnemonic, path, wordlist) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
if (!path) {
path = hdnode_1.defaultPath;
}
return new Wallet(yield (yield hdnode_1.HDNode.fromMnemonic(mnemonic, null, wordlist)).derivePath(path));
});
}
}
exports.Wallet = Wallet;
function verifyMessage(message, signature) {
return transactions_1.recoverAddress(hash_1.hashMessage(message), signature);
}
exports.verifyMessage = verifyMessage;
function verifyTypedData(domain, types,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value, signature) {
return transactions_1.recoverAddress(hash_1._TypedDataEncoder.hash(domain, types, value), signature);
}
exports.verifyTypedData = verifyTypedData;
//# sourceMappingURL=wallet.js.map