UNPKG

@ocap/wallet

Version:

Utility function to create and use an forge compatible crypto wallet

172 lines (171 loc) 6.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WalletType = void 0; exports.Wallet = Wallet; exports.fromSecretKey = fromSecretKey; exports.fromPublicKey = fromPublicKey; exports.fromAddress = fromAddress; exports.fromRandom = fromRandom; exports.fromJSON = fromJSON; exports.isValid = isValid; const util_1 = require("@ocap/util"); const mcrypto_1 = require("@ocap/mcrypto"); const did_1 = require("@arcblock/did"); exports.WalletType = did_1.DidType; /** * Generate an wallet instance that can be used to sign a message or verify a signature */ function Wallet(keyPair, t = 'default') { const type = (0, did_1.DidType)(t); const signer = (0, mcrypto_1.getSigner)(type.pk); const hasher = (0, mcrypto_1.getHasher)(type.hash); return { type, secretKey: keyPair.sk, publicKey: keyPair.pk, address: keyPair.pk ? (0, did_1.fromPublicKey)(keyPair.pk, type) : keyPair.address, // @ts-ignore hash(data, round = 1, encoding = 'hex') { return hasher(data, round, encoding); }, // @ts-ignore sign(data, hashBeforeSign = true, encoding = 'hex') { if (!keyPair.sk) { throw new Error('Cannot sign data without a secretKey'); } if (hashBeforeSign) { const hash = hasher(data, 1); return signer.sign(hash, keyPair.sk, encoding); } return signer.sign(data, keyPair.sk, encoding); }, // eslint-disable-next-line require-await async verify(data, signature, hashBeforeVerify = true, extra) { if (!keyPair.pk) { throw new Error('Cannot verify data without a publicKey'); } const hash = hashBeforeVerify ? hasher(data, 1) : data; return signer.verify(hash, signature, keyPair.pk, extra); }, ethHash(data) { if (typeof signer.ethHash !== 'function') { throw new Error('ethHash is not supported by signer'); } return signer.ethHash(data); }, ethSign(data, hashBeforeSign = true) { if (!keyPair.sk) { throw new Error('Cannot sign data without a secretKey'); } if (typeof signer.ethHash !== 'function') { throw new Error('ethSign is not supported by signer'); } if (hashBeforeSign) { return signer.ethSign(signer.ethHash(data), (0, util_1.toHex)(keyPair.sk)); } return signer.ethSign(data, (0, util_1.toHex)(keyPair.sk)); }, ethVerify(data, signature, hashBeforeVerify = true) { if (typeof signer.ethHash !== 'function') { throw new Error('ethVerify is not supported by signer'); } const hash = hashBeforeVerify ? signer.ethHash(data) : data; return signer.ethRecover(hash, signature) === this.address; }, // deprecated toAddress() { return keyPair.pk ? (0, did_1.fromPublicKey)(keyPair.pk, type) : keyPair.address; }, toJSON() { return { type: did_1.DidType.toJSON(type), sk: (0, util_1.toHex)(keyPair.sk), pk: (0, util_1.toHex)(keyPair.pk), address: this.address, }; }, }; } /** * Generate a wallet from secretKey * * @example * const assert = require('assert'); * const { fromSecretKey } = require('@ocap/wallet'); * * const sk = * '0xD67C071B6F51D2B61180B9B1AA9BE0DD0704619F0E30453AB4A592B036EDE644E4852B7091317E3622068E62A5127D1FB0D4AE2FC50213295E10652D2F0ABFC7'; * const sig = * '0x08a102851c38c072e42756c1cc70938b5499c8e9358dfe5f383823f56cdb282ffda60fcd581a02c6c673069e5afc0bf09abbe3639b61b84d64fd58ef9f083003'; * * const wallet = fromSecretKey(sk, type); * const message = 'data to sign'; * const signature = wallet.sign(message); * assert.equal(signature, sig, "signature should match"); * assert.ok(wallet.verify(message, signature), "signature should be verified"); */ function fromSecretKey(sk, _type = 'default') { const type = (0, did_1.DidType)(_type); const keyPair = { sk, pk: (0, mcrypto_1.getSigner)(type.pk).getPublicKey(sk) }; return Wallet(keyPair, type); } /** * Generate a wallet from publicKey */ function fromPublicKey(pk, _type = 'default') { return Wallet({ pk }, (0, did_1.DidType)(_type)); } /** * Generate a wallet from address (did) * * Since we do not know the publicKey and secretKey, this kind of wallet cannot be used for signing and verifying */ function fromAddress(address) { return Wallet({ address: (0, did_1.toAddress)(address) }, (0, did_1.toTypeInfo)(address)); } /** * Generate a wallet by generating a random secretKey */ function fromRandom(_type = 'default') { const type = (0, did_1.DidType)(_type); const signer = (0, mcrypto_1.getSigner)(type.pk); const keyPair = signer.genKeyPair(); return Wallet({ sk: keyPair.secretKey, pk: keyPair.publicKey }, type); } /** * Generating a wallet from a serialized json presentation of another wallet */ function fromJSON(json) { const type = did_1.DidType.fromJSON(json.type); // @ts-ignore return Wallet(json, type); } /** * Check if an object is valid wallet object */ function isValid(wallet, canSign = true) { if (!wallet || typeof wallet !== 'object') { return false; } if (typeof wallet.verify !== 'function') { return false; } if (typeof wallet.toAddress !== 'function') { return false; } if (typeof wallet.toJSON !== 'function') { return false; } if (!wallet.type || !wallet.publicKey) { return false; } if (canSign) { if (!wallet.secretKey) { return false; } if (typeof wallet.sign !== 'function') { return false; } } return true; }