UNPKG

@ocap/wallet

Version:

Utility function to create and use an forge compatible crypto wallet

152 lines (150 loc) 5.68 kB
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs'); let _arcblock_did = require("@arcblock/did"); let _arcblock_jwt = require("@arcblock/jwt"); _arcblock_jwt = require_rolldown_runtime.__toESM(_arcblock_jwt); let _ocap_mcrypto = require("@ocap/mcrypto"); let _ocap_util = require("@ocap/util"); //#region src/index.ts const WalletType = _arcblock_did.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, _arcblock_did.DidType)(t); const signer = (0, _ocap_mcrypto.getSigner)(type.pk); const hasher = (0, _ocap_mcrypto.getHasher)(type.hash); return { type, secretKey: keyPair.sk, publicKey: keyPair.pk, address: keyPair.pk ? (0, _arcblock_did.fromPublicKey)(keyPair.pk, type) : keyPair.address, hash(data, round = 1, encoding = "hex") { return hasher(data, round, encoding); }, async 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); }, 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); }, async signETH(data, hashBeforeSign = true) { if (!keyPair.sk) throw new Error("Cannot sign data without a secretKey"); if (typeof signer.ethHash !== "function" || typeof signer.ethSign !== "function") throw new Error("ethSign is not supported by signer"); if (hashBeforeSign) return signer.ethSign(signer.ethHash(data), (0, _ocap_util.toHex)(keyPair.sk)); return signer.ethSign(data, (0, _ocap_util.toHex)(keyPair.sk)); }, ethSign(data, hashBeforeSign = true) { return this.signETH(data, hashBeforeSign); }, async ethVerify(data, signature, hashBeforeVerify = true) { if (typeof signer.ethHash !== "function" || typeof signer.ethRecover !== "function") throw new Error("ethVerify is not supported by signer"); const hash = hashBeforeVerify ? signer.ethHash(data) : data; return signer.ethRecover(hash, signature) === this.address; }, async signJWT(payload = {}, doSign = true, version = "1.0.0") { if (!keyPair.sk) throw new Error("Cannot sign JWT without a secretKey"); return _arcblock_jwt.sign(this.address, keyPair.sk, payload, doSign, version); }, toAddress() { return keyPair.pk ? (0, _arcblock_did.fromPublicKey)(keyPair.pk, type) : keyPair.address; }, toJSON() { return { type: _arcblock_did.DidType.toJSON(type), sk: keyPair.sk ? (0, _ocap_util.toHex)(keyPair.sk) : "", pk: keyPair.pk ? (0, _ocap_util.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, _arcblock_did.DidType)(_type); return Wallet({ sk, pk: (0, _ocap_mcrypto.getSigner)(type.pk).getPublicKey(sk) }, type); } /** * Generate a wallet from publicKey */ function fromPublicKey(pk, _type = "default") { return Wallet({ pk }, (0, _arcblock_did.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, _arcblock_did.toAddress)(address) }, (0, _arcblock_did.toTypeInfo)(address)); } /** * Generate a wallet by generating a random secretKey */ function fromRandom(_type = "default") { const type = (0, _arcblock_did.DidType)(_type); const keyPair = (0, _ocap_mcrypto.getSigner)(type.pk).genKeyPair(); return Wallet({ sk: keyPair.secretKey, pk: keyPair.publicKey }, type); } /** * Generating a wallet from a serialized json presentation of another wallet */ function fromJSON(json) { return Wallet(json, _arcblock_did.DidType.fromJSON(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 (typeof wallet.sign !== "function") return false; } return true; } //#endregion exports.Wallet = Wallet; exports.WalletType = WalletType; exports.fromAddress = fromAddress; exports.fromJSON = fromJSON; exports.fromPublicKey = fromPublicKey; exports.fromRandom = fromRandom; exports.fromSecretKey = fromSecretKey; exports.isValid = isValid;