micro-eth-signer
Advanced tools
Comparing version 0.5.0 to 0.5.1
@@ -93,1 +93,2 @@ export function parseDecimal(s, precision) { | ||
} | ||
//# sourceMappingURL=formatters.js.map |
@@ -1,2 +0,1 @@ | ||
/*! micro-eth-signer - MIT License (c) Paul Miller (paulmillr.com) */ | ||
export declare const CHAIN_TYPES: { | ||
@@ -62,2 +61,3 @@ mainnet: number; | ||
constructor(data: string | Uint8Array | RawTx | RawTxMap, chain?: Chain, hardfork?: string, type?: Type); | ||
private isNew; | ||
get bytes(): Uint8Array; | ||
@@ -64,0 +64,0 @@ equals(other: Transaction): boolean; |
74
index.js
@@ -1,8 +0,33 @@ | ||
/*! micro-eth-signer - MIT License (c) Paul Miller (paulmillr.com) */ | ||
import { keccak_256 } from '@noble/hashes/sha3'; | ||
import { bytesToHex, hexToBytes as _hexToBytes } from '@noble/hashes/utils'; | ||
import * as secp256k1 from '@noble/secp256k1'; | ||
import RLP from 'rlp'; | ||
import * as RLP from '@ethereumjs/rlp'; | ||
export const CHAIN_TYPES = { mainnet: 1, ropsten: 3, rinkeby: 4, goerli: 5, kovan: 42 }; | ||
export const TRANSACTION_TYPES = { legacy: 0, eip2930: 1, eip1559: 2 }; | ||
const secp = { | ||
getPublicKey65b: (priv) => secp256k1.getPublicKey(priv, false), | ||
normalizePublicKeyTo65b: (pub) => secp256k1.Point.fromHex(pub).toRawBytes(false), | ||
sign: (msg, priv, opts) => { | ||
const [hex, recovery] = secp256k1.signSync(msg, priv, { | ||
recovered: true, | ||
extraEntropy: opts?.extraEntropy === false ? undefined : true, | ||
}); | ||
const { r, s } = secp256k1.Signature.fromHex(hex); | ||
return { r, s, recovery }; | ||
}, | ||
signAsync: async (msg, priv, opts) => { | ||
const [hex, recovery] = await secp256k1.sign(msg, priv, { | ||
recovered: true, | ||
extraEntropy: opts?.extraEntropy === false ? undefined : true, | ||
}); | ||
const { r, s } = secp256k1.Signature.fromHex(hex); | ||
return { r, s, recovery }; | ||
}, | ||
sigRecoverPub: (rsrec, msg, checkHighS = true) => { | ||
const sig = new secp256k1.Signature(rsrec.r, rsrec.s); | ||
if (checkHighS && sig.hasHighS()) | ||
throw new Error('Invalid signature: s is invalid'); | ||
return secp256k1.recoverPublicKey(msg, sig, rsrec.recovery); | ||
}, | ||
}; | ||
export function add0x(hex) { | ||
@@ -208,12 +233,7 @@ return /^0x/i.test(hex) ? hex : `0x${hex}`; | ||
key = hexToBytes(key); | ||
return Address.fromPublicKey(secp256k1.getPublicKey(key)); | ||
return Address.fromPublicKey(secp.getPublicKey65b(key)); | ||
}, | ||
fromPublicKey(key) { | ||
if (typeof key === 'string') | ||
key = hexToBytes(key); | ||
const len = key.length; | ||
if (![33, 65].includes(len)) | ||
throw new Error(`Invalid key with length "${len}"`); | ||
const pub = len === 65 ? key : secp256k1.Point.fromHex(key).toRawBytes(false); | ||
const addr = bytesToHex(keccak_256(pub.slice(1, 65))).slice(24); | ||
const pub = secp.normalizePublicKeyTo65b(key); | ||
const addr = bytesToHex(keccak_256(pub.subarray(1, 65))).slice(24); | ||
return Address.checksum(addr); | ||
@@ -303,2 +323,5 @@ }, | ||
} | ||
isNew() { | ||
return this.type === 'eip1559'; | ||
} | ||
get bytes() { | ||
@@ -314,2 +337,3 @@ return hexToBytes(this.hex); | ||
return k; | ||
return undefined; | ||
} | ||
@@ -323,3 +347,3 @@ get sender() { | ||
get gasPrice() { | ||
if (this.type === 'eip1559') | ||
if (this.isNew()) | ||
throw new Error('Field only available for "legacy" transactions'); | ||
@@ -329,3 +353,3 @@ return BigInt(this.raw.gasPrice); | ||
get maxFeePerGas() { | ||
if (this.type !== 'eip1559') | ||
if (!this.isNew()) | ||
throw new Error('Field only available for "eip1559" transactions'); | ||
@@ -335,3 +359,3 @@ return BigInt(this.raw.maxFeePerGas); | ||
get maxPriorityFeePerGas() { | ||
if (this.type !== 'eip1559') | ||
if (!this.isNew()) | ||
throw new Error('Field only available for "eip1559" transactions'); | ||
@@ -347,3 +371,3 @@ return BigInt(this.raw.maxPriorityFeePerGas); | ||
get fee() { | ||
const price = this.type === 'eip1559' ? this.maxFeePerGas : this.gasPrice; | ||
const price = this.isNew() ? this.maxFeePerGas : this.gasPrice; | ||
return price * this.gasLimit; | ||
@@ -391,10 +415,7 @@ } | ||
privateKey = strip0x(privateKey); | ||
const [hex, recovery] = await secp256k1.sign(this.getMessageToSign(), privateKey, { | ||
recovered: true, | ||
extraEntropy: extraEntropy === false ? undefined : true, | ||
}); | ||
const signature = secp256k1.Signature.fromHex(hex); | ||
const sig = await secp.signAsync(this.getMessageToSign(), privateKey, { extraEntropy }); | ||
const { recovery: rec } = sig; | ||
const chainId = Number(this.raw.chainId); | ||
const vv = this.type === 'legacy' ? (chainId ? recovery + (chainId * 2 + 35) : recovery + 27) : recovery; | ||
const [v, r, s] = [vv, signature.r, signature.s].map(numberTo0xHex); | ||
const vv = this.type === 'legacy' ? (chainId ? rec + (chainId * 2 + 35) : rec + 27) : rec; | ||
const [v, r, s] = [vv, sig.r, sig.s].map(numberTo0xHex); | ||
const signedRaw = this.type === 'legacy' | ||
@@ -408,12 +429,8 @@ ? { ...this.raw, v, r, s } | ||
throw new Error('Expected signed transaction: cannot recover sender of unsigned tx'); | ||
const [r, s] = [this.raw.r, this.raw.s].map(hexToNumber); | ||
const sig = new secp256k1.Signature(r, s); | ||
if (this.hardfork !== 'chainstart' && sig.hasHighS()) { | ||
throw new Error('Invalid signature: s is invalid'); | ||
} | ||
const signature = sig.toHex(); | ||
const v = Number(hexToNumber(this.type === 'legacy' ? this.raw.v : this.raw.yParity)); | ||
const chainId = Number(this.raw.chainId); | ||
const recovery = this.type === 'legacy' ? (chainId ? v - (chainId * 2 + 35) : v - 27) : v; | ||
return secp256k1.recoverPublicKey(this.getMessageToSign(), signature, recovery); | ||
const [r, s] = [this.raw.r, this.raw.s].map(hexToNumber); | ||
const checkHighS = this.hardfork !== 'chainstart'; | ||
return secp.sigRecoverPub({ r, s, recovery }, this.getMessageToSign(), checkHighS); | ||
} | ||
@@ -424,1 +441,2 @@ } | ||
Transaction.DEFAULT_TYPE = 'eip1559'; | ||
//# sourceMappingURL=index.js.map |
79
index.ts
@@ -1,7 +0,6 @@ | ||
/*! micro-eth-signer - MIT License (c) Paul Miller (paulmillr.com) */ | ||
/*! micro-eth-signer - MIT License (c) 2021 Paul Miller (paulmillr.com) */ | ||
import { keccak_256 } from '@noble/hashes/sha3'; | ||
import { bytesToHex, hexToBytes as _hexToBytes } from '@noble/hashes/utils'; | ||
import * as secp256k1 from '@noble/secp256k1'; | ||
import RLP from 'rlp'; | ||
import * as RLP from '@ethereumjs/rlp'; | ||
@@ -11,2 +10,31 @@ export const CHAIN_TYPES = { mainnet: 1, ropsten: 3, rinkeby: 4, goerli: 5, kovan: 42 }; | ||
type Hex = string | Uint8Array; | ||
type RSRec = { r: bigint; s: bigint; recovery: number }; | ||
type SignOpts = { extraEntropy?: boolean }; | ||
const secp = { | ||
getPublicKey65b: (priv: Hex) => secp256k1.getPublicKey(priv, false), | ||
normalizePublicKeyTo65b: (pub: Hex) => secp256k1.Point.fromHex(pub).toRawBytes(false), | ||
sign: (msg: Hex, priv: Hex, opts?: SignOpts): RSRec => { | ||
const [hex, recovery] = secp256k1.signSync(msg, priv, { | ||
recovered: true, | ||
extraEntropy: opts?.extraEntropy === false ? undefined : true, | ||
}); | ||
const { r, s } = secp256k1.Signature.fromHex(hex); | ||
return { r, s, recovery }; | ||
}, | ||
signAsync: async (msg: Hex, priv: Hex, opts?: SignOpts): Promise<RSRec> => { | ||
const [hex, recovery] = await secp256k1.sign(msg, priv, { | ||
recovered: true, | ||
extraEntropy: opts?.extraEntropy === false ? undefined : true, | ||
}); | ||
const { r, s } = secp256k1.Signature.fromHex(hex); | ||
return { r, s, recovery }; | ||
}, | ||
sigRecoverPub: (rsrec: RSRec, msg: Hex, checkHighS = true) => { | ||
const sig = new secp256k1.Signature(rsrec.r, rsrec.s); | ||
if (checkHighS && sig.hasHighS()) throw new Error('Invalid signature: s is invalid'); | ||
return secp256k1.recoverPublicKey(msg, sig, rsrec.recovery); | ||
}, | ||
}; | ||
export function add0x(hex: string) { | ||
@@ -260,11 +288,8 @@ return /^0x/i.test(hex) ? hex : `0x${hex}`; | ||
if (typeof key === 'string') key = hexToBytes(key); | ||
return Address.fromPublicKey(secp256k1.getPublicKey(key)); | ||
return Address.fromPublicKey(secp.getPublicKey65b(key)); | ||
}, | ||
fromPublicKey(key: string | Uint8Array): string { | ||
if (typeof key === 'string') key = hexToBytes(key); | ||
const len = key.length; | ||
if (![33, 65].includes(len)) throw new Error(`Invalid key with length "${len}"`); | ||
const pub = len === 65 ? key : secp256k1.Point.fromHex(key).toRawBytes(false); | ||
const addr = bytesToHex(keccak_256(pub.slice(1, 65))).slice(24); | ||
const pub = secp.normalizePublicKeyTo65b(key); | ||
const addr = bytesToHex(keccak_256(pub.subarray(1, 65))).slice(24); | ||
return Address.checksum(addr); | ||
@@ -363,2 +388,6 @@ }, | ||
private isNew() { | ||
return this.type === 'eip1559'; | ||
} | ||
get bytes(): Uint8Array { | ||
@@ -375,2 +404,3 @@ return hexToBytes(this.hex); | ||
if (CHAIN_TYPES[k as Chain] === Number(this.raw.chainId!)) return k as Chain; | ||
return undefined; | ||
} | ||
@@ -385,3 +415,3 @@ | ||
get gasPrice(): bigint { | ||
if (this.type === 'eip1559') throw new Error('Field only available for "legacy" transactions'); | ||
if (this.isNew()) throw new Error('Field only available for "legacy" transactions'); | ||
return BigInt(this.raw.gasPrice!); | ||
@@ -392,3 +422,3 @@ } | ||
get maxFeePerGas() { | ||
if (this.type !== 'eip1559') throw new Error('Field only available for "eip1559" transactions'); | ||
if (!this.isNew()) throw new Error('Field only available for "eip1559" transactions'); | ||
return BigInt(this.raw.maxFeePerGas!); | ||
@@ -398,3 +428,3 @@ } | ||
get maxPriorityFeePerGas() { | ||
if (this.type !== 'eip1559') throw new Error('Field only available for "eip1559" transactions'); | ||
if (!this.isNew()) throw new Error('Field only available for "eip1559" transactions'); | ||
return BigInt(this.raw.maxPriorityFeePerGas!); | ||
@@ -413,3 +443,3 @@ } | ||
get fee(): bigint { | ||
const price = this.type === 'eip1559' ? this.maxFeePerGas : this.gasPrice; | ||
const price = this.isNew() ? this.maxFeePerGas : this.gasPrice; | ||
return price * this.gasLimit; | ||
@@ -470,11 +500,7 @@ } | ||
if (typeof privateKey === 'string') privateKey = strip0x(privateKey); | ||
const [hex, recovery] = await secp256k1.sign(this.getMessageToSign(), privateKey, { | ||
recovered: true, | ||
extraEntropy: extraEntropy === false ? undefined : true, | ||
}); | ||
const signature = secp256k1.Signature.fromHex(hex); | ||
const sig = await secp.signAsync(this.getMessageToSign(), privateKey, { extraEntropy }); | ||
const { recovery: rec } = sig; | ||
const chainId = Number(this.raw.chainId!); | ||
const vv = | ||
this.type === 'legacy' ? (chainId ? recovery + (chainId * 2 + 35) : recovery + 27) : recovery; | ||
const [v, r, s] = [vv, signature.r, signature.s].map(numberTo0xHex); | ||
const vv = this.type === 'legacy' ? (chainId ? rec + (chainId * 2 + 35) : rec + 27) : rec; | ||
const [v, r, s] = [vv, sig.r, sig.s].map(numberTo0xHex); | ||
const signedRaw: RawTxMap = | ||
@@ -490,14 +516,9 @@ this.type === 'legacy' | ||
throw new Error('Expected signed transaction: cannot recover sender of unsigned tx'); | ||
const [r, s] = [this.raw.r, this.raw.s].map(hexToNumber); | ||
const sig = new secp256k1.Signature(r, s); | ||
// @ts-ignore | ||
if (this.hardfork !== 'chainstart' && sig.hasHighS()) { | ||
throw new Error('Invalid signature: s is invalid'); | ||
} | ||
const signature = sig.toHex(); | ||
const v = Number(hexToNumber(this.type === 'legacy' ? this.raw.v! : this.raw.yParity!)); | ||
const chainId = Number(this.raw.chainId!); | ||
const recovery = this.type === 'legacy' ? (chainId ? v - (chainId * 2 + 35) : v - 27) : v; | ||
return secp256k1.recoverPublicKey(this.getMessageToSign(), signature, recovery); | ||
const [r, s] = [this.raw.r, this.raw.s].map(hexToNumber); | ||
const checkHighS = this.hardfork !== 'chainstart'; | ||
return secp.sigRecoverPub({ r, s, recovery }, this.getMessageToSign(), checkHighS); | ||
} | ||
} |
{ | ||
"name": "micro-eth-signer", | ||
"version": "0.5.0", | ||
"version": "0.5.1", | ||
"description": "Create, sign and validate Ethereum transactions & addresses with minimum deps. Supports EIP1559", | ||
@@ -8,2 +8,3 @@ "type": "module", | ||
"module": "index.js", | ||
"types": "index.d.ts", | ||
"files": [ | ||
@@ -24,5 +25,5 @@ "index.js", | ||
"dependencies": { | ||
"@noble/hashes": "~1.1.2", | ||
"@noble/secp256k1": "~1.6.3", | ||
"rlp": "3.0.0" | ||
"@noble/hashes": "~1.2.0", | ||
"@noble/secp256k1": "~1.7.1", | ||
"@ethereumjs/rlp": "4.0.0" | ||
}, | ||
@@ -32,4 +33,4 @@ "devDependencies": { | ||
"@rollup/plugin-node-resolve": "13.3.0", | ||
"micro-bmark": "0.1.3", | ||
"micro-should": "0.1.4", | ||
"micro-bmark": "0.3.0", | ||
"micro-should": "0.4.0", | ||
"prettier": "2.6.2", | ||
@@ -67,7 +68,9 @@ "rollup": "2.75.5", | ||
"scripts": { | ||
"build": "tsc && rollup -c rollup.config.js", | ||
"build": "tsc", | ||
"build:release": "rollup -c rollup.config.js", | ||
"bench": "node test/benchmark.js", | ||
"lint": "prettier --print-width 100 --single-quote --check index.ts", | ||
"format": "prettier --print-width 100 --single-quote --write index.ts", | ||
"test": "node test/test.js" | ||
} | ||
} |
@@ -9,9 +9,4 @@ # micro-eth-signer | ||
Check out all web3 utility libraries: | ||
*Check out all web3 utility libraries:* [micro-eth-signer](https://github.com/paulmillr/micro-eth-signer), [micro-btc-signer](https://github.com/paulmillr/micro-btc-signer), [micro-sol-signer](https://github.com/paulmillr/micro-sol-signer), [micro-web3](https://github.com/paulmillr/micro-web3), [tx-tor-broadcaster](https://github.com/paulmillr/tx-tor-broadcaster) | ||
- [micro-eth-signer](https://github.com/paulmillr/micro-eth-signer) | ||
- [micro-sol-signer](https://github.com/paulmillr/micro-sol-signer) | ||
- [micro-web3](https://github.com/paulmillr/micro-web3) | ||
- [tx-tor-broadcaster](https://github.com/paulmillr/tx-tor-broadcaster) | ||
## Usage | ||
@@ -18,0 +13,0 @@ |
@@ -220,1 +220,2 @@ import { Address, add0x } from './index.js'; | ||
} | ||
//# sourceMappingURL=tx-validator.js.map |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
78872
1686
0
182
+ Added@ethereumjs/rlp@4.0.0
+ Added@ethereumjs/rlp@4.0.0(transitive)
+ Added@noble/hashes@1.2.0(transitive)
+ Added@noble/secp256k1@1.7.1(transitive)
- Removedrlp@3.0.0
- Removed@noble/hashes@1.1.5(transitive)
- Removed@noble/secp256k1@1.6.3(transitive)
- Removedrlp@3.0.0(transitive)
Updated@noble/hashes@~1.2.0
Updated@noble/secp256k1@~1.7.1