bitcoinjs-lib
Advanced tools
Comparing version 5.0.5 to 5.1.0
@@ -0,1 +1,14 @@ | ||
# 5.1.0 | ||
__added__ | ||
- A new `Psbt` class for creating, distributing, combining, signing, and compiling Transactions (#1425) | ||
- A `name` attribute to the Payment interface. P2SH and P2WSH are nested with `'-'` as separator, and p2ms is in the format of `'p2ms(m of n)''` all others are just hard coded. (#1433) | ||
__changed__ | ||
- `TransactionBuilder`: Migrate to stricter type checks during sign by switching to a single object parameter (#1416) | ||
- `tests`: Use regtest-client as separate library (#1421) | ||
# 5.0.5 | ||
__added__ | ||
- Added `ECPairInterface` `Stack` and `StackElement` interfaces to the main index.ts export (TypeScript only affected) | ||
# 5.0.4 | ||
@@ -2,0 +15,0 @@ __added__ |
{ | ||
"name": "bitcoinjs-lib", | ||
"version": "5.0.5", | ||
"version": "5.1.0", | ||
"description": "Client-side Bitcoin JavaScript library", | ||
@@ -50,2 +50,3 @@ "main": "./src/index.js", | ||
"bech32": "^1.1.2", | ||
"bip174": "^1.0.0", | ||
"bip32": "^2.0.3", | ||
@@ -78,2 +79,3 @@ "bip66": "^1.1.0", | ||
"proxyquire": "^2.0.1", | ||
"regtest-client": "0.1.0", | ||
"rimraf": "^2.6.3", | ||
@@ -80,0 +82,0 @@ "tslint": "^5.16.0", |
@@ -88,2 +88,10 @@ # BitcoinJS (bitcoinjs-lib) | ||
### Warning: Currently the tests use TransactionBuilder, which will be removed in the future (v6.x.x or higher) | ||
We will move towards replacing all instances of TransactionBuilder in the tests with the new Psbt. | ||
Currently we have a few examples on how to use the newer Psbt class at the following link: | ||
- [Psbt examples](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/transactions-psbt.js) | ||
The rest of the examples are below (using TransactionBuilder for Transaction creation) | ||
- [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js) | ||
@@ -90,0 +98,0 @@ - [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.js) |
@@ -19,2 +19,4 @@ 'use strict'; | ||
exports.Block = block_1.Block; | ||
var psbt_1 = require('./psbt'); | ||
exports.Psbt = psbt_1.Psbt; | ||
var script_1 = require('./script'); | ||
@@ -21,0 +23,0 @@ exports.opcodes = script_1.OPS; |
@@ -27,3 +27,3 @@ 'use strict'; | ||
const network = a.network || networks_1.bitcoin; | ||
const o = { network }; | ||
const o = { name: 'embed', network }; | ||
lazy.prop(o, 'output', () => { | ||
@@ -30,0 +30,0 @@ if (!a.data) return; |
@@ -96,2 +96,6 @@ 'use strict'; | ||
}); | ||
lazy.prop(o, 'name', () => { | ||
if (!o.m || !o.n) return; | ||
return `p2ms(${o.m} of ${o.n})`; | ||
}); | ||
// extended validation | ||
@@ -98,0 +102,0 @@ if (opts.validate) { |
@@ -29,3 +29,3 @@ 'use strict'; | ||
const network = a.network || networks_1.bitcoin; | ||
const o = { network }; | ||
const o = { name: 'p2pk', network }; | ||
lazy.prop(o, 'output', () => { | ||
@@ -32,0 +32,0 @@ if (!a.pubkey) return; |
@@ -39,3 +39,3 @@ 'use strict'; | ||
const network = a.network || networks_1.bitcoin; | ||
const o = { network }; | ||
const o = { name: 'p2pkh', network }; | ||
lazy.prop(o, 'address', () => { | ||
@@ -42,0 +42,0 @@ if (!o.hash) return; |
@@ -96,2 +96,7 @@ 'use strict'; | ||
}); | ||
lazy.prop(o, 'name', () => { | ||
const nameParts = ['p2sh']; | ||
if (o.redeem !== undefined) nameParts.push(o.redeem.name); | ||
return nameParts.join('-'); | ||
}); | ||
if (opts.validate) { | ||
@@ -98,0 +103,0 @@ let hash = Buffer.from([]); |
@@ -43,3 +43,3 @@ 'use strict'; | ||
const network = a.network || networks_1.bitcoin; | ||
const o = { network }; | ||
const o = { name: 'p2wpkh', network }; | ||
lazy.prop(o, 'address', () => { | ||
@@ -46,0 +46,0 @@ if (!o.hash) return; |
@@ -106,2 +106,7 @@ 'use strict'; | ||
}); | ||
lazy.prop(o, 'name', () => { | ||
const nameParts = ['p2wsh']; | ||
if (o.redeem !== undefined) nameParts.push(o.redeem.name); | ||
return nameParts.join('-'); | ||
}); | ||
// extended validation | ||
@@ -108,0 +113,0 @@ if (opts.validate) { |
@@ -16,2 +16,29 @@ 'use strict'; | ||
const SCRIPT_TYPES = classify.types; | ||
const PREVOUT_TYPES = new Set([ | ||
// Raw | ||
'p2pkh', | ||
'p2pk', | ||
'p2wpkh', | ||
'p2ms', | ||
// P2SH wrapped | ||
'p2sh-p2pkh', | ||
'p2sh-p2pk', | ||
'p2sh-p2wpkh', | ||
'p2sh-p2ms', | ||
// P2WSH wrapped | ||
'p2wsh-p2pkh', | ||
'p2wsh-p2pk', | ||
'p2wsh-p2ms', | ||
// P2SH-P2WSH wrapper | ||
'p2sh-p2wsh-p2pkh', | ||
'p2sh-p2wsh-p2pk', | ||
'p2sh-p2wsh-p2ms', | ||
]); | ||
function tfMessage(type, value, message) { | ||
try { | ||
typeforce(type, value); | ||
} catch (err) { | ||
throw new Error(message); | ||
} | ||
} | ||
function txIsString(tx) { | ||
@@ -34,2 +61,9 @@ return typeof tx === 'string' || tx instanceof String; | ||
this.__USE_LOW_R = false; | ||
console.warn( | ||
'Deprecation Warning: TransactionBuilder will be removed in the future. ' + | ||
'(v6.x.x or later) Please use the Psbt class instead. Examples of usage ' + | ||
'are available in the transactions-psbt.js integration test file on our ' + | ||
'Github. A high level explanation is available in the psbt.ts and psbt.js ' + | ||
'files as well.', | ||
); | ||
} | ||
@@ -123,70 +157,25 @@ static fromTransaction(transaction, network) { | ||
} | ||
sign(vin, keyPair, redeemScript, hashType, witnessValue, witnessScript) { | ||
// TODO: remove keyPair.network matching in 4.0.0 | ||
if (keyPair.network && keyPair.network !== this.network) | ||
throw new TypeError('Inconsistent network'); | ||
if (!this.__INPUTS[vin]) throw new Error('No input at index: ' + vin); | ||
hashType = hashType || transaction_1.Transaction.SIGHASH_ALL; | ||
if (this.__needsOutputs(hashType)) | ||
throw new Error('Transaction needs outputs'); | ||
const input = this.__INPUTS[vin]; | ||
// if redeemScript was previously provided, enforce consistency | ||
if ( | ||
input.redeemScript !== undefined && | ||
redeemScript && | ||
!input.redeemScript.equals(redeemScript) | ||
) { | ||
throw new Error('Inconsistent redeemScript'); | ||
} | ||
const ourPubKey = keyPair.publicKey || keyPair.getPublicKey(); | ||
if (!canSign(input)) { | ||
if (witnessValue !== undefined) { | ||
if (input.value !== undefined && input.value !== witnessValue) | ||
throw new Error('Input did not match witnessValue'); | ||
typeforce(types.Satoshi, witnessValue); | ||
input.value = witnessValue; | ||
} | ||
if (!canSign(input)) { | ||
const prepared = prepareInput( | ||
input, | ||
ourPubKey, | ||
redeemScript, | ||
witnessScript, | ||
); | ||
// updates inline | ||
Object.assign(input, prepared); | ||
} | ||
if (!canSign(input)) throw Error(input.prevOutType + ' not supported'); | ||
} | ||
// ready to sign | ||
let signatureHash; | ||
if (input.hasWitness) { | ||
signatureHash = this.__TX.hashForWitnessV0( | ||
vin, | ||
input.signScript, | ||
input.value, | ||
sign( | ||
signParams, | ||
keyPair, | ||
redeemScript, | ||
hashType, | ||
witnessValue, | ||
witnessScript, | ||
) { | ||
trySign( | ||
getSigningData( | ||
this.network, | ||
this.__INPUTS, | ||
this.__needsOutputs.bind(this), | ||
this.__TX, | ||
signParams, | ||
keyPair, | ||
redeemScript, | ||
hashType, | ||
); | ||
} else { | ||
signatureHash = this.__TX.hashForSignature( | ||
vin, | ||
input.signScript, | ||
hashType, | ||
); | ||
} | ||
// enforce in order signing of public keys | ||
const signed = input.pubkeys.some((pubKey, i) => { | ||
if (!ourPubKey.equals(pubKey)) return false; | ||
if (input.signatures[i]) throw new Error('Signature already exists'); | ||
// TODO: add tests | ||
if (ourPubKey.length !== 33 && input.hasWitness) { | ||
throw new Error( | ||
'BIP143 rejects uncompressed public keys in P2WPKH or P2WSH', | ||
); | ||
} | ||
const signature = keyPair.sign(signatureHash, this.__USE_LOW_R); | ||
input.signatures[i] = bscript.signature.encode(signature, hashType); | ||
return true; | ||
}); | ||
if (!signed) throw new Error('Key pair cannot sign for this input'); | ||
witnessValue, | ||
witnessScript, | ||
this.__USE_LOW_R, | ||
), | ||
); | ||
} | ||
@@ -752,1 +741,329 @@ __addInputUnsafe(txHash, vout, options) { | ||
} | ||
function checkSignArgs(inputs, signParams) { | ||
if (!PREVOUT_TYPES.has(signParams.prevOutScriptType)) { | ||
throw new TypeError( | ||
`Unknown prevOutScriptType "${signParams.prevOutScriptType}"`, | ||
); | ||
} | ||
tfMessage( | ||
typeforce.Number, | ||
signParams.vin, | ||
`sign must include vin parameter as Number (input index)`, | ||
); | ||
tfMessage( | ||
types.Signer, | ||
signParams.keyPair, | ||
`sign must include keyPair parameter as Signer interface`, | ||
); | ||
tfMessage( | ||
typeforce.maybe(typeforce.Number), | ||
signParams.hashType, | ||
`sign hashType parameter must be a number`, | ||
); | ||
const prevOutType = (inputs[signParams.vin] || []).prevOutType; | ||
const posType = signParams.prevOutScriptType; | ||
switch (posType) { | ||
case 'p2pkh': | ||
if (prevOutType && prevOutType !== 'pubkeyhash') { | ||
throw new TypeError( | ||
`input #${signParams.vin} is not of type p2pkh: ${prevOutType}`, | ||
); | ||
} | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.witnessScript, | ||
`${posType} requires NO witnessScript`, | ||
); | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.redeemScript, | ||
`${posType} requires NO redeemScript`, | ||
); | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.witnessValue, | ||
`${posType} requires NO witnessValue`, | ||
); | ||
break; | ||
case 'p2pk': | ||
if (prevOutType && prevOutType !== 'pubkey') { | ||
throw new TypeError( | ||
`input #${signParams.vin} is not of type p2pk: ${prevOutType}`, | ||
); | ||
} | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.witnessScript, | ||
`${posType} requires NO witnessScript`, | ||
); | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.redeemScript, | ||
`${posType} requires NO redeemScript`, | ||
); | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.witnessValue, | ||
`${posType} requires NO witnessValue`, | ||
); | ||
break; | ||
case 'p2wpkh': | ||
if (prevOutType && prevOutType !== 'witnesspubkeyhash') { | ||
throw new TypeError( | ||
`input #${signParams.vin} is not of type p2wpkh: ${prevOutType}`, | ||
); | ||
} | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.witnessScript, | ||
`${posType} requires NO witnessScript`, | ||
); | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.redeemScript, | ||
`${posType} requires NO redeemScript`, | ||
); | ||
tfMessage( | ||
types.Satoshi, | ||
signParams.witnessValue, | ||
`${posType} requires witnessValue`, | ||
); | ||
break; | ||
case 'p2ms': | ||
if (prevOutType && prevOutType !== 'multisig') { | ||
throw new TypeError( | ||
`input #${signParams.vin} is not of type p2ms: ${prevOutType}`, | ||
); | ||
} | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.witnessScript, | ||
`${posType} requires NO witnessScript`, | ||
); | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.redeemScript, | ||
`${posType} requires NO redeemScript`, | ||
); | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.witnessValue, | ||
`${posType} requires NO witnessValue`, | ||
); | ||
break; | ||
case 'p2sh-p2wpkh': | ||
if (prevOutType && prevOutType !== 'scripthash') { | ||
throw new TypeError( | ||
`input #${signParams.vin} is not of type p2sh-p2wpkh: ${prevOutType}`, | ||
); | ||
} | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.witnessScript, | ||
`${posType} requires NO witnessScript`, | ||
); | ||
tfMessage( | ||
typeforce.Buffer, | ||
signParams.redeemScript, | ||
`${posType} requires redeemScript`, | ||
); | ||
tfMessage( | ||
types.Satoshi, | ||
signParams.witnessValue, | ||
`${posType} requires witnessValue`, | ||
); | ||
break; | ||
case 'p2sh-p2ms': | ||
case 'p2sh-p2pk': | ||
case 'p2sh-p2pkh': | ||
if (prevOutType && prevOutType !== 'scripthash') { | ||
throw new TypeError( | ||
`input #${signParams.vin} is not of type ${posType}: ${prevOutType}`, | ||
); | ||
} | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.witnessScript, | ||
`${posType} requires NO witnessScript`, | ||
); | ||
tfMessage( | ||
typeforce.Buffer, | ||
signParams.redeemScript, | ||
`${posType} requires redeemScript`, | ||
); | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.witnessValue, | ||
`${posType} requires NO witnessValue`, | ||
); | ||
break; | ||
case 'p2wsh-p2ms': | ||
case 'p2wsh-p2pk': | ||
case 'p2wsh-p2pkh': | ||
if (prevOutType && prevOutType !== 'witnessscripthash') { | ||
throw new TypeError( | ||
`input #${signParams.vin} is not of type ${posType}: ${prevOutType}`, | ||
); | ||
} | ||
tfMessage( | ||
typeforce.Buffer, | ||
signParams.witnessScript, | ||
`${posType} requires witnessScript`, | ||
); | ||
tfMessage( | ||
typeforce.value(undefined), | ||
signParams.redeemScript, | ||
`${posType} requires NO redeemScript`, | ||
); | ||
tfMessage( | ||
types.Satoshi, | ||
signParams.witnessValue, | ||
`${posType} requires witnessValue`, | ||
); | ||
break; | ||
case 'p2sh-p2wsh-p2ms': | ||
case 'p2sh-p2wsh-p2pk': | ||
case 'p2sh-p2wsh-p2pkh': | ||
if (prevOutType && prevOutType !== 'scripthash') { | ||
throw new TypeError( | ||
`input #${signParams.vin} is not of type ${posType}: ${prevOutType}`, | ||
); | ||
} | ||
tfMessage( | ||
typeforce.Buffer, | ||
signParams.witnessScript, | ||
`${posType} requires witnessScript`, | ||
); | ||
tfMessage( | ||
typeforce.Buffer, | ||
signParams.redeemScript, | ||
`${posType} requires witnessScript`, | ||
); | ||
tfMessage( | ||
types.Satoshi, | ||
signParams.witnessValue, | ||
`${posType} requires witnessScript`, | ||
); | ||
break; | ||
} | ||
} | ||
function trySign({ | ||
input, | ||
ourPubKey, | ||
keyPair, | ||
signatureHash, | ||
hashType, | ||
useLowR, | ||
}) { | ||
// enforce in order signing of public keys | ||
let signed = false; | ||
for (const [i, pubKey] of input.pubkeys.entries()) { | ||
if (!ourPubKey.equals(pubKey)) continue; | ||
if (input.signatures[i]) throw new Error('Signature already exists'); | ||
// TODO: add tests | ||
if (ourPubKey.length !== 33 && input.hasWitness) { | ||
throw new Error( | ||
'BIP143 rejects uncompressed public keys in P2WPKH or P2WSH', | ||
); | ||
} | ||
const signature = keyPair.sign(signatureHash, useLowR); | ||
input.signatures[i] = bscript.signature.encode(signature, hashType); | ||
signed = true; | ||
} | ||
if (!signed) throw new Error('Key pair cannot sign for this input'); | ||
} | ||
function getSigningData( | ||
network, | ||
inputs, | ||
needsOutputs, | ||
tx, | ||
signParams, | ||
keyPair, | ||
redeemScript, | ||
hashType, | ||
witnessValue, | ||
witnessScript, | ||
useLowR, | ||
) { | ||
let vin; | ||
if (typeof signParams === 'number') { | ||
console.warn( | ||
'DEPRECATED: TransactionBuilder sign method arguments ' + | ||
'will change in v6, please use the TxbSignArg interface', | ||
); | ||
vin = signParams; | ||
} else if (typeof signParams === 'object') { | ||
checkSignArgs(inputs, signParams); | ||
({ | ||
vin, | ||
keyPair, | ||
redeemScript, | ||
hashType, | ||
witnessValue, | ||
witnessScript, | ||
} = signParams); | ||
} else { | ||
throw new TypeError( | ||
'TransactionBuilder sign first arg must be TxbSignArg or number', | ||
); | ||
} | ||
if (keyPair === undefined) { | ||
throw new Error('sign requires keypair'); | ||
} | ||
// TODO: remove keyPair.network matching in 4.0.0 | ||
if (keyPair.network && keyPair.network !== network) | ||
throw new TypeError('Inconsistent network'); | ||
if (!inputs[vin]) throw new Error('No input at index: ' + vin); | ||
hashType = hashType || transaction_1.Transaction.SIGHASH_ALL; | ||
if (needsOutputs(hashType)) throw new Error('Transaction needs outputs'); | ||
const input = inputs[vin]; | ||
// if redeemScript was previously provided, enforce consistency | ||
if ( | ||
input.redeemScript !== undefined && | ||
redeemScript && | ||
!input.redeemScript.equals(redeemScript) | ||
) { | ||
throw new Error('Inconsistent redeemScript'); | ||
} | ||
const ourPubKey = | ||
keyPair.publicKey || (keyPair.getPublicKey && keyPair.getPublicKey()); | ||
if (!canSign(input)) { | ||
if (witnessValue !== undefined) { | ||
if (input.value !== undefined && input.value !== witnessValue) | ||
throw new Error('Input did not match witnessValue'); | ||
typeforce(types.Satoshi, witnessValue); | ||
input.value = witnessValue; | ||
} | ||
if (!canSign(input)) { | ||
const prepared = prepareInput( | ||
input, | ||
ourPubKey, | ||
redeemScript, | ||
witnessScript, | ||
); | ||
// updates inline | ||
Object.assign(input, prepared); | ||
} | ||
if (!canSign(input)) throw Error(input.prevOutType + ' not supported'); | ||
} | ||
// ready to sign | ||
let signatureHash; | ||
if (input.hasWitness) { | ||
signatureHash = tx.hashForWitnessV0( | ||
vin, | ||
input.signScript, | ||
input.value, | ||
hashType, | ||
); | ||
} else { | ||
signatureHash = tx.hashForSignature(vin, input.signScript, hashType); | ||
} | ||
return { | ||
input, | ||
ourPubKey, | ||
keyPair, | ||
signatureHash, | ||
hashType, | ||
useLowR: !!useLowR, | ||
}; | ||
} |
@@ -16,2 +16,10 @@ 'use strict'; | ||
}; | ||
function Signer(obj) { | ||
return ( | ||
(typeforce.Buffer(obj.publicKey) || | ||
typeof obj.getPublicKey === 'function') && | ||
typeof obj.sign === 'function' | ||
); | ||
} | ||
exports.Signer = Signer; | ||
const SATOSHI_MAX = 21 * 1e14; | ||
@@ -18,0 +26,0 @@ function Satoshi(value) { |
@@ -8,11 +8,20 @@ /// <reference types="node" /> | ||
} | ||
export interface ECPairInterface { | ||
export interface Signer { | ||
publicKey: Buffer; | ||
network?: Network; | ||
sign(hash: Buffer, lowR?: boolean): Buffer; | ||
getPublicKey?(): Buffer; | ||
} | ||
export interface SignerAsync { | ||
publicKey: Buffer; | ||
network?: Network; | ||
sign(hash: Buffer, lowR?: boolean): Promise<Buffer>; | ||
getPublicKey?(): Buffer; | ||
} | ||
export interface ECPairInterface extends Signer { | ||
compressed: boolean; | ||
network: Network; | ||
publicKey: Buffer; | ||
privateKey?: Buffer; | ||
toWIF(): string; | ||
sign(hash: Buffer, lowR?: boolean): Buffer; | ||
verify(hash: Buffer, signature: Buffer): boolean; | ||
getPublicKey?(): Buffer; | ||
} | ||
@@ -19,0 +28,0 @@ declare class ECPair implements ECPairInterface { |
@@ -10,2 +10,3 @@ import * as bip32 from 'bip32'; | ||
export { Block } from './block'; | ||
export { Psbt } from './psbt'; | ||
export { OPS as opcodes } from './script'; | ||
@@ -15,3 +16,3 @@ export { Transaction } from './transaction'; | ||
export { BIP32Interface } from 'bip32'; | ||
export { ECPairInterface } from './ecpair'; | ||
export { ECPairInterface, Signer, SignerAsync } from './ecpair'; | ||
export { Network } from './networks'; | ||
@@ -18,0 +19,0 @@ export { Payment, PaymentOpts, Stack, StackElement } from './payments'; |
@@ -11,2 +11,3 @@ /// <reference types="node" /> | ||
export interface Payment { | ||
name?: string; | ||
network?: Network; | ||
@@ -13,0 +14,0 @@ output?: Buffer; |
/// <reference types="node" /> | ||
import { ECPairInterface } from './ecpair'; | ||
import { Signer } from './ecpair'; | ||
import { Network } from './networks'; | ||
import { Transaction } from './transaction'; | ||
interface TxbSignArg { | ||
prevOutScriptType: string; | ||
vin: number; | ||
keyPair: Signer; | ||
redeemScript?: Buffer; | ||
hashType?: number; | ||
witnessValue?: number; | ||
witnessScript?: Buffer; | ||
} | ||
export declare class TransactionBuilder { | ||
@@ -21,3 +30,3 @@ network: Network; | ||
buildIncomplete(): Transaction; | ||
sign(vin: number, keyPair: ECPairInterface, redeemScript?: Buffer, hashType?: number, witnessValue?: number, witnessScript?: Buffer): void; | ||
sign(signParams: number | TxbSignArg, keyPair?: Signer, redeemScript?: Buffer, hashType?: number, witnessValue?: number, witnessScript?: Buffer): void; | ||
private __addInputUnsafe; | ||
@@ -30,1 +39,2 @@ private __build; | ||
} | ||
export {}; |
@@ -6,2 +6,3 @@ export declare function UInt31(value: number): boolean; | ||
} | ||
export declare function Signer(obj: any): boolean; | ||
export declare function Satoshi(value: number): boolean; | ||
@@ -8,0 +9,0 @@ export declare const ECPoint: any; |
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
210484
94
5514
170
16
16
+ Addedbip174@^1.0.0
+ Addedbip174@1.0.1(transitive)