From 356ab597a3c429c0d820459a64e827cfb3039960 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Fri, 4 Aug 2023 11:12:41 +0100 Subject: [PATCH 1/3] export signTransaction --- src/accounts/index.ts | 5 +++++ src/accounts/utils/signTransaction.ts | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/accounts/index.ts b/src/accounts/index.ts index 7d430ab84b..12ec3e748d 100644 --- a/src/accounts/index.ts +++ b/src/accounts/index.ts @@ -23,6 +23,11 @@ export { type SignMessageReturnType, signMessage, } from './utils/signMessage.js' +export { + type SignTransactionParameters, + type SignTransactionReturnType, + signTransaction, +} from './utils/signTransaction.js' export { type SignTypedDataParameters, type SignTypedDataReturnType, diff --git a/src/accounts/utils/signTransaction.ts b/src/accounts/utils/signTransaction.ts index d19807ebb0..86b16d3fa0 100644 --- a/src/accounts/utils/signTransaction.ts +++ b/src/accounts/utils/signTransaction.ts @@ -12,7 +12,7 @@ import { import { sign } from './sign.js' -export type SignTransactionArgs< +export type SignTransactionParameters< TTransactionSerializable extends TransactionSerializable = TransactionSerializable, > = { privateKey: Hex @@ -31,7 +31,7 @@ export async function signTransaction< privateKey, transaction, serializer = serializeTransaction, -}: SignTransactionArgs): Promise< +}: SignTransactionParameters): Promise< SignTransactionReturnType > { const signature = await sign({ From 443e8064a657bb6dec4ebdfbef20e2fd343dec9c Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Fri, 4 Aug 2023 11:12:52 +0100 Subject: [PATCH 2/3] update docs --- site/docs/accounts/custom.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/site/docs/accounts/custom.md b/site/docs/accounts/custom.md index 09a8c4a091..4b01bf55ef 100644 --- a/site/docs/accounts/custom.md +++ b/site/docs/accounts/custom.md @@ -25,10 +25,9 @@ import { toAccount } from 'viem/accounts' ## Usage ```ts -import { createWalletClient, http } from 'viem' -import { toAccount } from 'viem/accounts' // [!code focus] +import { createWalletClient, getAddress, http } from 'viem' +import { signMessage, signTransaction, toAccount } from 'viem/accounts' // [!code focus] import { mainnet } from 'viem/chains' -import { getAddress, signMessage, signTransaction } from './sign-utils' // [!code focus] const privateKey = '0x...' // [!code focus:13] const account = toAccount({ From 55ccd860f3d6a49d9c65068917d8134ce7928078 Mon Sep 17 00:00:00 2001 From: "moxey.eth" Date: Thu, 10 Aug 2023 05:57:35 +0200 Subject: [PATCH 3/3] refactor --- .changeset/ninety-goats-grab.md | 5 +++++ site/docs/accounts/custom.md | 12 ++++++++--- site/docs/accounts/signMessage.md | 2 +- site/docs/accounts/signTransaction.md | 6 ++++-- site/docs/accounts/signTypedData.md | 2 +- src/accounts/index.ts | 1 + .../utils/privateKeyToAddress.test.ts | 10 ++++++++++ src/accounts/utils/privateKeyToAddress.ts | 20 +++++++++++++++++++ 8 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 .changeset/ninety-goats-grab.md create mode 100644 src/accounts/utils/privateKeyToAddress.test.ts create mode 100644 src/accounts/utils/privateKeyToAddress.ts diff --git a/.changeset/ninety-goats-grab.md b/.changeset/ninety-goats-grab.md new file mode 100644 index 0000000000..0c88f9bcf3 --- /dev/null +++ b/.changeset/ninety-goats-grab.md @@ -0,0 +1,5 @@ +--- +"viem": minor +--- + +Added `signTransaction` & `privateKeyToAddress` exports to `viem/accounts` entrypoint. diff --git a/site/docs/accounts/custom.md b/site/docs/accounts/custom.md index 4b01bf55ef..010d6a5d23 100644 --- a/site/docs/accounts/custom.md +++ b/site/docs/accounts/custom.md @@ -25,8 +25,14 @@ import { toAccount } from 'viem/accounts' ## Usage ```ts -import { createWalletClient, getAddress, http } from 'viem' -import { signMessage, signTransaction, toAccount } from 'viem/accounts' // [!code focus] +import { createWalletClient, http } from 'viem' +import { // [!code focus:7] + signMessage, + signTransaction, + signTypedData, + privateKeyToAddress, + toAccount +} from 'viem/accounts' import { mainnet } from 'viem/chains' const privateKey = '0x...' // [!code focus:13] @@ -129,4 +135,4 @@ const account = toAccount({ return signTypedData({ ...typedData, privateKey }) }, }) -``` \ No newline at end of file +``` diff --git a/site/docs/accounts/signMessage.md b/site/docs/accounts/signMessage.md index 047eee80ba..59b3002282 100644 --- a/site/docs/accounts/signMessage.md +++ b/site/docs/accounts/signMessage.md @@ -24,7 +24,7 @@ With the calculated signature, you can: ## Usage ```ts -import { privateKeyToAccount } from 'viem' +import { privateKeyToAccount } from 'viem/accounts' const account = privateKeyToAccount('0x...') diff --git a/site/docs/accounts/signTransaction.md b/site/docs/accounts/signTransaction.md index ef95df4018..4fc717343d 100644 --- a/site/docs/accounts/signTransaction.md +++ b/site/docs/accounts/signTransaction.md @@ -19,7 +19,8 @@ Signs a transaction with the Account's private key. ## Usage ```ts -import { privateKeyToAccount, parseGwei } from 'viem' +import { parseGwei } from 'viem' +import { privateKeyToAccount } from 'viem/accounts' const account = privateKeyToAccount('0x...') @@ -38,7 +39,8 @@ const signature = await account.signTransaction({ viem has a built-in serializer for **Legacy**, **EIP-2930** (`0x01`) and **EIP-1559** (`0x02`) transaction types. If you would like to serialize on another transaction type that viem does not support internally, you can pass a custom serializer. ```ts -import { privateKeyToAccount, parseGwei } from 'viem' +import { parseGwei } from 'viem' +import { privateKeyToAccount } from 'viem/accounts' const account = privateKeyToAccount('0x...') diff --git a/site/docs/accounts/signTypedData.md b/site/docs/accounts/signTypedData.md index 38c782eede..d0a76bf819 100644 --- a/site/docs/accounts/signTypedData.md +++ b/site/docs/accounts/signTypedData.md @@ -21,7 +21,7 @@ Signs typed data and calculates an Ethereum-specific signature in [https://eips. ::: code-group ```ts [example.ts] -import { privateKeyToAccount } from 'viem' +import { privateKeyToAccount } from 'viem/accounts' import { domain, types } from './data' const account = privateKeyToAccount('0x...') diff --git a/src/accounts/index.ts b/src/accounts/index.ts index 12ec3e748d..0813a2ca40 100644 --- a/src/accounts/index.ts +++ b/src/accounts/index.ts @@ -35,6 +35,7 @@ export { } from './utils/signTypedData.js' export { parseAccount } from './utils/parseAccount.js' export { publicKeyToAddress } from './utils/publicKeyToAddress.js' +export { privateKeyToAddress } from './utils/privateKeyToAddress.js' export { czech } from './wordlists/czech.js' export { english } from './wordlists/english.js' export { french } from './wordlists/french.js' diff --git a/src/accounts/utils/privateKeyToAddress.test.ts b/src/accounts/utils/privateKeyToAddress.test.ts new file mode 100644 index 0000000000..e20afecfc9 --- /dev/null +++ b/src/accounts/utils/privateKeyToAddress.test.ts @@ -0,0 +1,10 @@ +import { expect, test } from 'vitest' + +import { accounts } from '../../_test/constants.js' +import { privateKeyToAddress } from './privateKeyToAddress.js' + +test('default', () => { + expect(privateKeyToAddress(accounts[0].privateKey).toLowerCase()).toEqual( + accounts[0].address, + ) +}) diff --git a/src/accounts/utils/privateKeyToAddress.ts b/src/accounts/utils/privateKeyToAddress.ts new file mode 100644 index 0000000000..5e3f7d3fcd --- /dev/null +++ b/src/accounts/utils/privateKeyToAddress.ts @@ -0,0 +1,20 @@ +import { secp256k1 } from '@noble/curves/secp256k1' +import type { Address } from 'abitype' + +import type { Hex } from '../../types/misc.js' +import { bytesToHex } from '../../utils/encoding/toHex.js' +import { publicKeyToAddress } from './publicKeyToAddress.js' + +/** + * @description Converts an ECDSA private key to an address. + * + * @param privateKey The private key to convert. + * + * @returns The address. + */ +export function privateKeyToAddress(privateKey: Hex): Address { + const publicKey = bytesToHex( + secp256k1.getPublicKey(privateKey.slice(2), false), + ) + return publicKeyToAddress(publicKey) +}