UNPKG

@ckb-ccc/core

Version:

Core of CCC - CKBer's Codebase

66 lines (54 loc) 1.95 kB
import { secp256k1 } from "@noble/curves/secp256k1"; import { bytesConcat, bytesFrom, BytesLike } from "../../bytes/index.js"; import { Transaction, TransactionLike, WitnessArgs } from "../../ckb/index.js"; import { Client } from "../../client/index.js"; import { Hex, hexFrom, HexLike } from "../../hex/index.js"; import { numBeToBytes } from "../../num/index.js"; import { SignerCkbPublicKey } from "./signerCkbPublicKey.js"; import { messageHashCkbSecp256k1 } from "./verifyCkbSecp256k1.js"; /** * @public */ export class SignerCkbPrivateKey extends SignerCkbPublicKey { public readonly privateKey: Hex; constructor(client: Client, privateKey: HexLike) { const pk = hexFrom(privateKey); if (bytesFrom(pk).length !== 32) { throw new Error("Private key must be 32 bytes!"); } super(client, secp256k1.getPublicKey(bytesFrom(pk), true)); this.privateKey = pk; } async _signMessage(message: HexLike): Promise<Hex> { const signature = secp256k1.sign( bytesFrom(message), bytesFrom(this.privateKey), ); const { r, s, recovery } = signature; return hexFrom( bytesConcat( numBeToBytes(r, 32), numBeToBytes(s, 32), numBeToBytes(recovery, 1), ), ); } async signMessageRaw(message: string | BytesLike): Promise<Hex> { return this._signMessage(messageHashCkbSecp256k1(message)); } async signOnlyTransaction(txLike: TransactionLike): Promise<Transaction> { const tx = Transaction.from(txLike); for (const { script } of await this.getRelatedScripts(tx)) { const info = await tx.getSignHashInfo(script, this.client); if (!info) { return tx; } const signature = await this._signMessage(info.message); const witness = tx.getWitnessArgsAt(info.position) ?? WitnessArgs.from({}); witness.lock = signature; tx.setWitnessArgsAt(info.position, witness); } return tx; } }