UNPKG

@pact-toolbox/signers

Version:
135 lines (129 loc) 5.74 kB
import { TextEncoder, base16, base64Url, blake2b, createKeyPairFromBytes, createKeyPairFromPrivateKeyBytes, exportBase16Key, generateKeyPair, signBytes, utf8 } from "@pact-toolbox/crypto"; //#region src/command-signer.ts /** Checks whether the provided value implements the {@link PactCommandSigner} interface. */ function isPactCommandSigner(value) { return "signPactCommands" in value && typeof value.signPactCommands === "function"; } /** Asserts that the provided value implements the {@link PactCommandSigner} interface. */ function assertIsPactCommandSigner(value) { if (!isPactCommandSigner(value)) throw new Error("Value is not a PactCommandSigner"); } async function partiallySignPactCommand(keyPairs, command) { const cmd = JSON.stringify(command); const cmdBytes = utf8.encode(cmd); const hash = blake2b(cmdBytes, void 0, 32); const keyPairMap = /* @__PURE__ */ new Map(); for (const keyPair of keyPairs) { const pubKeyHex = await exportBase16Key(keyPair.publicKey); keyPairMap.set(pubKeyHex, keyPair); } const sigs = []; for (const signer of command.signers) { const pubKey = signer.pubKey; const keyPair = keyPairMap.get(pubKey); if (!keyPair) { sigs.push({ pubKey }); continue; } const signatureBytes = await signBytes(keyPair.privateKey, hash); const signatureHex = base16.decode(signatureBytes); sigs.push({ pubKey, sig: signatureHex }); } return { cmd, hash, sigs }; } function isTransactionFullSig(sig) { return "sig" in sig && sig.sig !== void 0; } function isFullySignedTransaction(transaction) { return typeof transaction === "object" && transaction !== null && "cmd" in transaction && "hash" in transaction && "sigs" in transaction && Array.isArray(transaction.sigs) && transaction.sigs.every(isTransactionFullSig); } function finalizeTransaction(transaction) { return Object.freeze({ cmd: transaction.cmd, hash: typeof transaction.hash !== "string" && transaction.hash instanceof Uint8Array ? base64Url.decode(transaction.hash) : transaction.hash, sigs: transaction.sigs.filter((sig) => "sig" in sig) }); } //#endregion //#region src/message-signer.ts /** Checks whether the provided value implements the {@link MessageSigner} interface. */ function isMessageSigner(value) { return "signMessages" in value && typeof value.signMessages === "function"; } /** Asserts that the provided value implements the {@link MessageSigner} interface. */ function assertIsMessageSigner(value) { if (!isMessageSigner(value)) throw new Error("Value is not a MessageSigner"); } //#endregion //#region src/keypair-signer.ts /** Checks whether the provided value implements the {@link KeyPairSigner} interface. */ function isKeyPairSigner(value) { return "keyPair" in value && typeof value.keyPair === "object" && isMessageSigner(value) && isPactCommandSigner(value); } /** Asserts that the provided value implements the {@link KeyPairSigner} interface. */ function assertIsKeyPairSigner(value) { if (!isKeyPairSigner(value)) throw new Error("Value is not a KeyPairSigner"); } /** Creates a KeyPairSigner from the provided Crypto KeyPair. */ async function createSignerFromKeyPair(keyPair) { const address = await exportBase16Key(keyPair.publicKey); const out = { address, keyPair, signMessages: (messages) => { return Promise.all(messages.map(async (message) => Object.freeze({ [address]: await signBytes(keyPair.privateKey, message.content) }))); }, signPactCommands: (commands) => { return Promise.all(commands.map((cmd) => partiallySignPactCommand([keyPair], cmd))); } }; return Object.freeze(out); } /** Securely generates a signer capable of signing messages and transactions using a Crypto KeyPair. */ async function generateKeyPairSigner() { return createSignerFromKeyPair(await generateKeyPair()); } /** Creates a signer capable of signing messages and transactions using the 64 bytes of a KeyPair. */ async function createKeyPairSignerFromBytes(bytes, extractable) { return createSignerFromKeyPair(await createKeyPairFromBytes(bytes, extractable)); } /** Creates a signer capable of signing messages and transactions using the 32 bytes of a private key. */ async function createKeyPairSignerFromPrivateKeyBytes(bytes, extractable) { return createSignerFromKeyPair(await createKeyPairFromPrivateKeyBytes(bytes, extractable)); } async function createKeyPairSignerFromBase16PrivateKey(privateKey, extractable) { return createKeyPairSignerFromPrivateKeyBytes(base16.encode(privateKey), extractable); } //#endregion //#region src/noop.ts /** Creates a NoopSigner from the provided Address. */ function createNoopSigner(address) { const out = { address, signMessages: (messages) => Promise.resolve(messages.map(() => Object.freeze({}))), signPactCommands: (commands) => Promise.resolve(commands.map(() => Object.freeze({}))) }; return Object.freeze(out); } //#endregion //#region src/signable-message.ts /** * Creates a signable message from a provided content. * If a string is provided, it will be UTF-8 encoded. */ function createSignableMessage(content, signatures = {}) { return Object.freeze({ content: typeof content === "string" ? new TextEncoder().encode(content) : content, signatures: Object.freeze({ ...signatures }) }); } //#endregion export { assertIsKeyPairSigner, assertIsMessageSigner, assertIsPactCommandSigner, createKeyPairSignerFromBase16PrivateKey, createKeyPairSignerFromBytes, createKeyPairSignerFromPrivateKeyBytes, createNoopSigner, createSignableMessage, createSignerFromKeyPair, finalizeTransaction, generateKeyPairSigner, isFullySignedTransaction, isKeyPairSigner, isMessageSigner, isPactCommandSigner, isTransactionFullSig, partiallySignPactCommand }; //# sourceMappingURL=index.browser.mjs.map