From 78bf3216bd9f7df33b311705d83275cfa0258489 Mon Sep 17 00:00:00 2001 From: Artur Kozak Date: Thu, 14 Feb 2019 17:07:48 +0100 Subject: [PATCH] Add typings for eth-sig-util --- types/eth-sig-util/eth-sig-util-tests.ts | 98 ++++++++++++ types/eth-sig-util/index.d.ts | 184 +++++++++++++++++++++++ types/eth-sig-util/tsconfig.json | 23 +++ types/eth-sig-util/tslint.json | 1 + 4 files changed, 306 insertions(+) create mode 100644 types/eth-sig-util/eth-sig-util-tests.ts create mode 100644 types/eth-sig-util/index.d.ts create mode 100644 types/eth-sig-util/tsconfig.json create mode 100644 types/eth-sig-util/tslint.json diff --git a/types/eth-sig-util/eth-sig-util-tests.ts b/types/eth-sig-util/eth-sig-util-tests.ts new file mode 100644 index 0000000000..33f5840d05 --- /dev/null +++ b/types/eth-sig-util/eth-sig-util-tests.ts @@ -0,0 +1,98 @@ +import * as util from 'eth-sig-util'; + +const hex32 = '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'; +const buffer32 = Buffer.from(hex32, 'hex'); + +util.concatSig(28, buffer32, buffer32); +util.normalize(hex32); +util.normalize(42); + +//////////////////////////////////////////////////////////////////////////////// +// Personal message signing utils + +const messageSig = util.personalSign(buffer32, { data: 'test data' }); +util.recoverPersonalSignature({ data: 'test data', sig: messageSig }); +util.extractPublicKey({ data: 'test data', sig: messageSig }); + +//////////////////////////////////////////////////////////////////////////////// +// EIP-712 legacy draft utils + +const legacyTypedData = [{ + type: 'uint32', + name: 'testValue', + value: 42, +}, { + type: 'string', + name: 'testName', + value: 'test value', +}]; +util.typedSignatureHash(legacyTypedData); +const typedSigLegacy = util.signTypedDataLegacy(buffer32, { data: legacyTypedData }); +util.recoverTypedSignatureLegacy({ data: legacyTypedData, sig: typedSigLegacy }); + +//////////////////////////////////////////////////////////////////////////////// +// Elliptic curve encryption utils + +util.getEncryptionPublicKey(hex32); +const encPubkey = util.getEncryptionPublicKey(buffer32); +const encMessage = util.encrypt(encPubkey, { data: 'test data' }, 'x25519-xsalsa20-poly1305'); +util.decrypt(encMessage, buffer32); +util.decrypt(encMessage, hex32); +const encData = util.encryptSafely(encPubkey, { data: legacyTypedData }, 'x25519-xsalsa20-poly1305'); +util.decryptSafely(encData, buffer32); +util.decryptSafely(encData, hex32); + +//////////////////////////////////////////////////////////////////////////////// +// EIP-712 current draft utils + +// Sample data from the official EIP-712 example: +// https://github.com/ethereum/EIPs/blob/master/assets/eip-712/Example.js +const typedData = { + types: { + EIP712Domain: [ + { name: 'name', type: 'string' }, + { name: 'version', type: 'string' }, + { name: 'chainId', type: 'uint256' }, + { name: 'verifyingContract', type: 'address' }, + ], + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' } + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' } + ], + }, + primaryType: 'Mail', + domain: { + name: 'Ether Mail', + version: '1', + chainId: 1, + verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', + }, + message: { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello, Bob!', + }, +}; +const typedMessage = typedData.message; +const types = typedData.types; +const primaryType = typedData.primaryType; +util.TypedDataUtils.encodeData(primaryType, typedMessage, types); +util.TypedDataUtils.encodeType(primaryType, types); +util.TypedDataUtils.findTypeDependencies(primaryType, types); +util.TypedDataUtils.hashStruct(primaryType, typedMessage, types); +util.TypedDataUtils.hashType(primaryType, types); +util.TypedDataUtils.sanitizeData(typedData); +util.TypedDataUtils.sign(typedData); +const typedSig = util.signTypedData(buffer32, { data: typedData }); +util.recoverTypedSignature({ data: typedData, sig: typedSig }); diff --git a/types/eth-sig-util/index.d.ts b/types/eth-sig-util/index.d.ts new file mode 100644 index 0000000000..61369ddc86 --- /dev/null +++ b/types/eth-sig-util/index.d.ts @@ -0,0 +1,184 @@ +// Type definitions for eth-sig-util 2.1 +// Project: https://github.com/MetaMask/eth-sig-util#readme +// Definitions by: Artur Kozak +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.3 + +/// + +/** + * @returns a 0x-prefixed 130-byte signature. + */ +export function concatSig(v: number, r: Buffer, s: Buffer): string; + +/** + * @param input a number or a hex string (either 0x-prefixed or not). + * @returns a 0x-prefixed hex string. + */ +export function normalize(input: string | number): string; + +//////////////////////////////////////////////////////////////////////////////// +// Personal message signing utils + +export interface MessageData { data: T; } + +export interface SignedMessageData extends MessageData { sig: string; } + +export function personalSign(privateKey: Buffer, message: MessageData): string; + +export function recoverPersonalSignature(message: SignedMessageData): string; + +export function extractPublicKey(message: SignedMessageData): string; + +//////////////////////////////////////////////////////////////////////////////// +// EIP-712 legacy draft utils + +export interface EIP712LegacyField { + type: string; + name: string; + value: any; +} + +export type EIP712LegacyData = ReadonlyArray; + +export function typedSignatureHash(data: EIP712LegacyData): string; + +export function signTypedDataLegacy( + privateKey: Buffer, + message: MessageData, +): string; + +export function recoverTypedSignatureLegacy( + message: SignedMessageData, +): string; + +//////////////////////////////////////////////////////////////////////////////// +// Elliptic curve encryption utils + +export type EncryptionType = 'x25519-xsalsa20-poly1305'; + +export interface EncryptedData { + version: EncryptionType; + nonce: string; + ephemPublicKey: string; + ciphertext: string; +} + +/** + * @param receiverPublicKey a 32-byte base64 string, e.g. from @see `getEncryptionPublicKey` + * @param data a utf-8 string to be encrypted + * @param version one of the supported encryption schemes, @see `EncryptionType` + */ +export function encrypt( + receiverPublicKey: string, + data: MessageData, + version: EncryptionType, +): EncryptedData; + +/** + * Same as @see `encrypt`, but encrypts a JSON object. + */ +export function encryptSafely( + receiverPublicKey: string, + data: MessageData, + version: EncryptionType, +): EncryptedData; + +/** + * @param encryptedData result of @see `encrypt`. + * @param receiverPrivateKey should be a 32-byte Buffer or *not* 0x-prefixed hex string. + */ +export function decrypt( + encryptedData: EncryptedData, + receiverPrivateKey: string | Buffer, +): string; + +/** + * @param encryptedData result of @see `encryptSafely`. + * @param receiverPrivateKey should be a 32-byte Buffer or *not* 0x-prefixed hex string. + */ +export function decryptSafely( + encryptedData: EncryptedData, + receiverPrivateKey: string | Buffer, +): any; + +/** + * @param privateKey should be a 32-byte Buffer or *not* 0x-prefixed hex string. + * @returns a 32-byte public key as a base64 string. + */ +export function getEncryptionPublicKey(privateKey: string | Buffer): string; + +//////////////////////////////////////////////////////////////////////////////// +// EIP-712 current draft utils + +export interface EIP712TypeProperty { + name: string; + type: string; +} + +/** + * Maps type name to an array describing its properties' types. + * Should include the `EIP712Domain` struct description. + */ +export interface EIP712Types { + [name: string]: ReadonlyArray; +} + +export interface EIP712Message { + [key: string]: any; +} + +/** + * The standard requires to use at least one of these fields. + * @see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#definition-of-domainseparator + */ +export interface EIP712Domain { + name?: string; + version?: string; + chainId?: string | number; + verifyingContract?: string; + salt?: string; +} + +export interface EIP712TypedData { + types: EIP712Types; + primaryType: string; + domain: EIP712Domain; + message: EIP712Message; +} + +export namespace TypedDataUtils { + function encodeData(primaryType: string, data: EIP712Message, types: EIP712Types): Buffer; + + function encodeType(primaryType: string, types: EIP712Types): string; + + function findTypeDependencies( + primaryType: string, types: EIP712Types, + ): string[]; + + function hashStruct(primaryType: string, data: EIP712Message, types: EIP712Types): Buffer; + + function hashType(primaryType: string, types: EIP712Types): Buffer; + + function sanitizeData(data: EIP712TypedData): EIP712TypedData; + + /** + * @returns hash of the typed data as defined by EIP712 (contrary to the function's name) + * @see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#specification + */ + function sign(data: EIP712TypedData): Buffer; +} + +/** + * A JSON Schema object equivalent to the EIP712Message type. + */ +export const TYPED_MESSAGE_SCHEMA: any; + +export function signTypedData( + privateKey: Buffer, + msgParams: MessageData, +): string; + +export function recoverTypedSignature( + msgParams: SignedMessageData, +): string; diff --git a/types/eth-sig-util/tsconfig.json b/types/eth-sig-util/tsconfig.json new file mode 100644 index 0000000000..18e346c208 --- /dev/null +++ b/types/eth-sig-util/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "eth-sig-util-tests.ts" + ] +} diff --git a/types/eth-sig-util/tslint.json b/types/eth-sig-util/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/eth-sig-util/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }