New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

unielon-coin-bitcoin

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

unielon-coin-bitcoin - npm Package Compare versions

Comparing version 1.0.4 to 1.0.5

20

dist/bitcoinjs-lib/psbt.d.ts

@@ -72,2 +72,6 @@ /// <reference types="node" />

signTaprootInput(inputIndex: number, keyPair: Signer, tapLeafHashToSign?: Buffer, sighashTypes?: number[]): this;
getHashAndSighashType(inputIndex: number, publicKey: Buffer, sighashTypes?: number[]): {
hash: Buffer;
sighashType: number;
};
private _signInput;

@@ -92,2 +96,14 @@ private _signTaprootInput;

}
interface PsbtCache {
__NON_WITNESS_UTXO_TX_CACHE: Transaction[];
__NON_WITNESS_UTXO_BUF_CACHE: Buffer[];
__TX_IN_CACHE: {
[index: string]: number;
};
__TX: Transaction;
__FEE_RATE?: number;
__FEE?: number;
__EXTRACTED_TX?: Transaction;
__UNSAFE_SIGN_NONSEGWIT: boolean;
}
interface PsbtOptsOptional {

@@ -141,3 +157,7 @@ network?: Network;

};
export declare function getHashAndSighashType(inputs: PsbtInput[], inputIndex: number, pubkey: Buffer, cache: PsbtCache, sighashTypes: number[]): {
hash: Buffer;
sighashType: number;
};
type AllScriptType = 'witnesspubkeyhash' | 'pubkeyhash' | 'multisig' | 'pubkey' | 'nonstandard' | 'p2sh-witnesspubkeyhash' | 'p2sh-pubkeyhash' | 'p2sh-multisig' | 'p2sh-pubkey' | 'p2sh-nonstandard' | 'p2wsh-pubkeyhash' | 'p2wsh-multisig' | 'p2wsh-pubkey' | 'p2wsh-nonstandard' | 'p2sh-p2wsh-pubkeyhash' | 'p2sh-p2wsh-multisig' | 'p2sh-p2wsh-pubkey' | 'p2sh-p2wsh-nonstandard';
export {};

10

dist/bitcoinjs-lib/psbt.js

@@ -26,3 +26,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Psbt = void 0;
exports.getHashAndSighashType = exports.Psbt = void 0;
const psbt_1 = require("./bip174/psbt");

@@ -110,3 +110,4 @@ const varuint = __importStar(require("./bip174/converter/varint"));

}
catch (_) { }
catch (_) {
}
return {

@@ -504,2 +505,6 @@ script: (0, bufferutils_1.cloneBuffer)(output.script),

}
getHashAndSighashType(inputIndex, publicKey, sighashTypes = [transaction_1.Transaction.SIGHASH_ALL]) {
const { hash, sighashType } = getHashAndSighashType(this.data.inputs, inputIndex, publicKey, this.__CACHE, sighashTypes);
return { hash, sighashType };
}
_signInput(inputIndex, keyPair, sighashTypes = [transaction_1.Transaction.SIGHASH_ALL]) {

@@ -933,2 +938,3 @@ const { hash, sighashType } = getHashAndSighashType(this.data.inputs, inputIndex, keyPair.publicKey, this.__CACHE, sighashTypes);

}
exports.getHashAndSighashType = getHashAndSighashType;
function getHashForSig(inputIndex, input, cache, forValidate, sighashTypes) {

@@ -935,0 +941,0 @@ const unsignedTx = cache.__TX;

27

dist/psbtSign.d.ts
import { Psbt } from "./bitcoinjs-lib/psbt";
import { Network } from './bitcoinjs-lib';
import { utxoTx, BuyingData, ListingData } from './type';
export declare function buildPsbt(tx: utxoTx, network?: Network): string;
export declare function psbtSign(psbtBase64: string, privateKey: string, network?: Network): string;
import { BuyingData, ListingData, signPsbtOptions, toSignInput, utxoTx } from './type';
export declare function buildPsbt(tx: utxoTx, network?: Network, maximumFeeRate?: number): string;
export declare function classicToPsbt(tx: utxoTx, network?: Network, maximumFeeRate?: number): Psbt;
export declare function psbtSign(psbtBase64: string, privateKey: string, network?: Network, maximumFeeRate?: number): string;
export declare function signPsbtWithKeyPathAndScriptPathBatch(psbtHexs: string[], privateKey: string, network?: Network, opts?: signPsbtOptions[]): string[];
export declare function signPsbtWithKeyPathAndScriptPath(psbtStr: string, privateKey: string, network?: Network, opts?: signPsbtOptions): string;
export declare function signPsbtWithKeyPathAndScriptPathImpl(psbt: Psbt, privateKey: string, network?: Network, autoFinalized?: boolean, signInputs?: toSignInput[]): void;
export declare function psbtSignImpl(psbt: Psbt, privateKey: string, network?: Network): void;
export declare function extractPsbtTransaction(txHex: string, network?: Network): string;
export declare function extractPsbtTransaction(txHex: string, network?: Network, maximumFeeRate?: number): string;
export declare function generateUnsignedListingPsbt(listingData: ListingData, network?: Network, publicKey?: string): string;

@@ -13,1 +17,16 @@ export declare function generateSignedListingPsbt(listingData: ListingData, privateKey: string, network?: Network): string;

export declare function generateSignedBuyingTx(buyingData: BuyingData, privateKey: string, network?: Network): string;
export declare function generateMPCUnsignedListingPSBT(psbtBase64: string, pubKeyHex: string, network?: Network): {
psbtBase64: string;
signHashList: string[];
};
export declare function generateMPCSignedListingPSBT(psbtBase64: string, pubKeyHex: string, signature: string, network?: Network): string;
export declare function generateMPCUnsignedBuyingPSBT(psbtBase64: string, pubKeyHex: string, network?: Network, batchSize?: number): {
psbtBase64: string;
signHashList: string[];
};
export declare function generateMPCSignedBuyingTx(psbtBase64: string, pubKeyHex: string, signatureList: string[], network?: Network, batchSize?: number): string;
export declare function generateMPCUnsignedPSBT(psbtStr: string, pubKeyHex: string, network?: Network): {
psbtStr: string;
signHashList: string[];
};
export declare function generateMPCSignedPSBT(psbtStr: string, pubKeyHex: string, signatureList: string[], network?: Network): string;

@@ -26,3 +26,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.generateSignedBuyingTx = exports.mergeSignedBuyingPsbt = exports.generateUnsignedBuyingPsbt = exports.generateSignedListingPsbt = exports.generateUnsignedListingPsbt = exports.extractPsbtTransaction = exports.psbtSignImpl = exports.psbtSign = exports.buildPsbt = void 0;
exports.generateMPCSignedPSBT = exports.generateMPCUnsignedPSBT = exports.generateMPCSignedBuyingTx = exports.generateMPCUnsignedBuyingPSBT = exports.generateMPCSignedListingPSBT = exports.generateMPCUnsignedListingPSBT = exports.generateSignedBuyingTx = exports.mergeSignedBuyingPsbt = exports.generateUnsignedBuyingPsbt = exports.generateSignedListingPsbt = exports.generateUnsignedListingPsbt = exports.extractPsbtTransaction = exports.psbtSignImpl = exports.signPsbtWithKeyPathAndScriptPathImpl = exports.signPsbtWithKeyPathAndScriptPath = exports.signPsbtWithKeyPathAndScriptPathBatch = exports.psbtSign = exports.classicToPsbt = exports.buildPsbt = void 0;
const psbt_1 = require("./bitcoinjs-lib/psbt");

@@ -37,5 +37,14 @@ const crypto_lib_1 = require("@okxweb3/crypto-lib");

const psbtutils_1 = require("./bitcoinjs-lib/psbt/psbtutils");
const bscript = __importStar(require("./bitcoinjs-lib/script"));
const crypto_1 = require("./bitcoinjs-lib/crypto");
const crypto_2 = require("crypto");
const schnorr = crypto_lib_1.signUtil.schnorr.secp256k1.schnorr;
function buildPsbt(tx, network) {
const psbt = new psbt_1.Psbt({ network });
const defaultMaximumFeeRate = 5000;
function buildPsbt(tx, network, maximumFeeRate) {
const psbt = classicToPsbt(tx, network, maximumFeeRate);
return psbt.toHex();
}
exports.buildPsbt = buildPsbt;
function classicToPsbt(tx, network, maximumFeeRate) {
const psbt = new psbt_1.Psbt({ network, maximumFeeRate: maximumFeeRate ? maximumFeeRate : defaultMaximumFeeRate });
tx.inputs.forEach((input) => {

@@ -113,7 +122,10 @@ const outputScript = (0, address_1.toOutputScript)(input.address, network);

});
return psbt.toHex();
return psbt;
}
exports.buildPsbt = buildPsbt;
function psbtSign(psbtBase64, privateKey, network) {
const psbt = psbt_1.Psbt.fromBase64(psbtBase64, { network });
exports.classicToPsbt = classicToPsbt;
function psbtSign(psbtBase64, privateKey, network, maximumFeeRate) {
const psbt = psbt_1.Psbt.fromBase64(psbtBase64, {
network,
maximumFeeRate: maximumFeeRate ? maximumFeeRate : defaultMaximumFeeRate
});
psbtSignImpl(psbt, privateKey, network);

@@ -123,2 +135,126 @@ return psbt.toBase64();

exports.psbtSign = psbtSign;
function signPsbtWithKeyPathAndScriptPathBatch(psbtHexs, privateKey, network, opts) {
if (psbtHexs == undefined || psbtHexs.length == 0) {
return [];
}
let res = [];
const optsSize = opts == undefined ? 0 : opts.length;
let i = 0;
for (i = 0; i < psbtHexs.length; i++) {
let opt = {};
if (i < optsSize && opts) {
opt = opts[i];
}
const signedPsbt = signPsbtWithKeyPathAndScriptPath(psbtHexs[i], privateKey, network, {
autoFinalized: opt.autoFinalized,
toSignInputs: opt.toSignInputs
});
res.push(signedPsbt);
}
return res;
}
exports.signPsbtWithKeyPathAndScriptPathBatch = signPsbtWithKeyPathAndScriptPathBatch;
function signPsbtWithKeyPathAndScriptPath(psbtStr, privateKey, network, opts = {}) {
const psbt = getPsbtFromString(psbtStr, network);
signPsbtWithKeyPathAndScriptPathImpl(psbt, privateKey, network, opts.autoFinalized, opts.toSignInputs);
return psbt.toHex();
}
exports.signPsbtWithKeyPathAndScriptPath = signPsbtWithKeyPathAndScriptPath;
function signPsbtWithKeyPathAndScriptPathImpl(psbt, privateKey, network, autoFinalized, signInputs) {
network = network || bitcoinjs_lib_1.networks.bitcoin;
const privKeyHex = (0, txBuild_1.privateKeyFromWIF)(privateKey, network);
const signInputMap = new Map();
if (signInputs != undefined) {
signInputs.map(e => {
signInputMap.set(e.index, e);
});
}
const signer = {
psbtIndex: 0,
needTweak: true,
tweakHash: Buffer.alloc(0),
toSignInputsMap: signInputMap,
publicKey: Buffer.alloc(0),
sign(hash) {
return (0, txBuild_1.sign)(hash, privKeyHex);
},
signSchnorr(hash) {
let tweakedPrivKey = taproot.taprootTweakPrivKey(crypto_lib_1.base.fromHex(privKeyHex));
if (this.toSignInputsMap?.has(this.psbtIndex)) {
if (this.toSignInputsMap.get(this.psbtIndex)?.disableTweakSigner) {
return Buffer.from(schnorr.sign(hash, privKeyHex, crypto_lib_1.base.randomBytes(32)));
}
}
if (!this.needTweak) {
return Buffer.from(schnorr.sign(hash, privKeyHex, crypto_lib_1.base.randomBytes(32)));
}
if (this.needTweak && this.tweakHash.length > 0) {
tweakedPrivKey = taproot.taprootTweakPrivKey(crypto_lib_1.base.fromHex(privKeyHex), this.tweakHash);
}
return Buffer.from(schnorr.sign(hash, tweakedPrivKey, crypto_lib_1.base.randomBytes(32)));
},
};
let allowedSighashTypes = [
bitcoinjs_lib_1.Transaction.SIGHASH_SINGLE | bitcoinjs_lib_1.Transaction.SIGHASH_ANYONECANPAY,
bitcoinjs_lib_1.Transaction.SIGHASH_ALL,
bitcoinjs_lib_1.Transaction.SIGHASH_DEFAULT
];
for (let i = 0; i < psbt.inputCount; i++) {
if (signInputMap?.size > 0 && !signInputMap?.has(i)) {
continue;
}
signer.psbtIndex = i;
const input = psbt.data.inputs[i];
if ((0, bip371_1.isTaprootInput)(input)) {
if (!input.tapInternalKey) {
input.tapInternalKey = (0, bip371_1.toXOnly)((0, txBuild_1.wif2Public)(privateKey, network));
}
signer.needTweak = true;
signer.publicKey = Buffer.from(taproot.taprootTweakPubkey((0, bip371_1.toXOnly)((0, txBuild_1.wif2Public)(privateKey, network)))[0]);
if (signInputMap?.has(i)) {
if (signInputMap?.get(i)?.disableTweakSigner) {
signer.publicKey = (0, txBuild_1.wif2Public)(privateKey, network);
signer.needTweak = false;
}
}
if (input.tapLeafScript && input.tapLeafScript?.length > 0 && !input.tapMerkleRoot) {
input.tapLeafScript.map(e => {
if (e.controlBlock && e.script) {
signer.publicKey = (0, txBuild_1.wif2Public)(privateKey, network);
signer.needTweak = false;
}
});
}
else if (input.tapMerkleRoot) {
signer.needTweak = true;
signer.tweakHash = input.tapMerkleRoot;
signer.publicKey = Buffer.from(taproot.taprootTweakPubkey((0, bip371_1.toXOnly)((0, txBuild_1.wif2Public)(privateKey, network)), input.tapMerkleRoot)[0]);
}
}
else {
signer.needTweak = false;
signer.tweakHash = Buffer.alloc(0);
signer.publicKey = (0, txBuild_1.wif2Public)(privateKey, network);
}
try {
if (signInputMap?.has(i)) {
const sighashTypes = signInputMap?.get(i)?.sighashTypes;
if (sighashTypes != undefined) {
allowedSighashTypes = sighashTypes;
}
}
psbt.signInput(i, signer, allowedSighashTypes);
if (autoFinalized != undefined && !autoFinalized) {
continue;
}
psbt.finalizeInput(i);
}
catch (e) {
if (signInputMap?.size > 0 && signInputMap?.has(i)) {
throw e;
}
}
}
}
exports.signPsbtWithKeyPathAndScriptPathImpl = signPsbtWithKeyPathAndScriptPathImpl;
function psbtSignImpl(psbt, privateKey, network) {

@@ -139,2 +275,3 @@ network = network || bitcoinjs_lib_1.networks.bitcoin;

bitcoinjs_lib_1.Transaction.SIGHASH_SINGLE | bitcoinjs_lib_1.Transaction.SIGHASH_ANYONECANPAY,
bitcoinjs_lib_1.Transaction.SIGHASH_ALL | bitcoinjs_lib_1.Transaction.SIGHASH_ANYONECANPAY,
bitcoinjs_lib_1.Transaction.SIGHASH_ALL,

@@ -145,2 +282,6 @@ bitcoinjs_lib_1.Transaction.SIGHASH_DEFAULT

if ((0, bip371_1.isTaprootInput)(psbt.data.inputs[i])) {
const input = psbt.data.inputs[i];
if (!input.tapInternalKey) {
input.tapInternalKey = (0, bip371_1.toXOnly)((0, txBuild_1.wif2Public)(privateKey, network));
}
signer.publicKey = Buffer.from(taproot.taprootTweakPubkey((0, bip371_1.toXOnly)((0, txBuild_1.wif2Public)(privateKey, network)))[0]);

@@ -154,8 +295,12 @@ }

}
catch (e) { }
catch (e) {
}
}
}
exports.psbtSignImpl = psbtSignImpl;
function extractPsbtTransaction(txHex, network) {
const psbt = psbt_1.Psbt.fromHex(txHex, { network });
function extractPsbtTransaction(txHex, network, maximumFeeRate) {
const psbt = psbt_1.Psbt.fromHex(txHex, {
network,
maximumFeeRate: maximumFeeRate ? maximumFeeRate : defaultMaximumFeeRate
});
let extractedTransaction;

@@ -167,2 +312,3 @@ try {

extractedTransaction = psbt.extractTransaction();
console.log(e);
}

@@ -321,2 +467,151 @@ return extractedTransaction.toHex();

exports.generateSignedBuyingTx = generateSignedBuyingTx;
function generateMPCUnsignedListingPSBT(psbtBase64, pubKeyHex, network) {
const psbt = psbt_1.Psbt.fromBase64(psbtBase64, { network });
const publicKey = crypto_lib_1.base.fromHex(pubKeyHex);
const sighashTypes = [bitcoinjs_lib_1.Transaction.SIGHASH_SINGLE | bitcoinjs_lib_1.Transaction.SIGHASH_ANYONECANPAY];
let signHashList = [];
for (let i = 0; i < psbt.inputCount; i++) {
if (i != SELLER_INDEX) {
continue;
}
const { hash, sighashType } = psbt.getHashAndSighashType(i, publicKey, sighashTypes);
signHashList.push(crypto_lib_1.base.toHex(hash));
}
return {
psbtBase64: psbtBase64,
signHashList: signHashList,
};
}
exports.generateMPCUnsignedListingPSBT = generateMPCUnsignedListingPSBT;
function generateMPCSignedListingPSBT(psbtBase64, pubKeyHex, signature, network) {
const psbt = psbt_1.Psbt.fromBase64(psbtBase64, { network });
const publicKey = crypto_lib_1.base.fromHex(pubKeyHex);
const partialSig = [
{
pubkey: publicKey,
signature: bscript.signature.encode(crypto_lib_1.base.fromHex(signature), bitcoinjs_lib_1.Transaction.SIGHASH_SINGLE | bitcoinjs_lib_1.Transaction.SIGHASH_ANYONECANPAY),
},
];
psbt.data.updateInput(SELLER_INDEX, { partialSig });
return psbt.toBase64();
}
exports.generateMPCSignedListingPSBT = generateMPCSignedListingPSBT;
function generateMPCUnsignedBuyingPSBT(psbtBase64, pubKeyHex, network, batchSize = 1) {
const psbt = psbt_1.Psbt.fromBase64(psbtBase64, { network });
const publicKey = crypto_lib_1.base.fromHex(pubKeyHex);
const sighashTypes = [bitcoinjs_lib_1.Transaction.SIGHASH_ALL];
let signHashList = [];
const sellerIndex = batchSize + 1;
for (let i = 0; i < psbt.inputCount; i++) {
if (i >= sellerIndex && i < sellerIndex + batchSize) {
continue;
}
const { hash, sighashType } = psbt.getHashAndSighashType(i, publicKey, sighashTypes);
signHashList.push(crypto_lib_1.base.toHex(hash));
}
return {
psbtBase64: psbtBase64,
signHashList: signHashList,
};
}
exports.generateMPCUnsignedBuyingPSBT = generateMPCUnsignedBuyingPSBT;
function generateMPCSignedBuyingTx(psbtBase64, pubKeyHex, signatureList, network, batchSize = 1) {
const psbt = psbt_1.Psbt.fromBase64(psbtBase64, { network });
const publicKey = crypto_lib_1.base.fromHex(pubKeyHex);
const sellerIndex = batchSize + 1;
for (let i = 0; i < psbt.inputCount; i++) {
if (i >= sellerIndex && i < sellerIndex + batchSize) {
continue;
}
const partialSig = [
{
pubkey: publicKey,
signature: bscript.signature.encode(crypto_lib_1.base.fromHex(signatureList[i]), bitcoinjs_lib_1.Transaction.SIGHASH_ALL),
},
];
psbt.data.updateInput(i, { partialSig });
}
return extractPsbtTransaction(psbt.toHex(), network);
}
exports.generateMPCSignedBuyingTx = generateMPCSignedBuyingTx;
function generateMPCUnsignedPSBT(psbtStr, pubKeyHex, network) {
const psbt = getPsbtFromString(psbtStr, network);
const publicKey = crypto_lib_1.base.fromHex(pubKeyHex);
const allowedSighashTypes = [
bitcoinjs_lib_1.Transaction.SIGHASH_SINGLE | bitcoinjs_lib_1.Transaction.SIGHASH_ANYONECANPAY,
bitcoinjs_lib_1.Transaction.SIGHASH_SINGLE | bitcoinjs_lib_1.Transaction.SIGHASH_ANYONECANPAY,
bitcoinjs_lib_1.Transaction.SIGHASH_ALL | bitcoinjs_lib_1.Transaction.SIGHASH_ANYONECANPAY,
bitcoinjs_lib_1.Transaction.SIGHASH_ALL,
bitcoinjs_lib_1.Transaction.SIGHASH_DEFAULT
];
;
let signHashList = [];
for (let i = 0; i < psbt.inputCount; i++) {
try {
const { hash, sighashType } = psbt.getHashAndSighashType(i, publicKey, allowedSighashTypes);
signHashList.push(crypto_lib_1.base.toHex(hash));
}
catch (e) {
const s = getRandomHash();
signHashList.push(s);
}
}
const m = new Map();
signHashList.map((e, i) => {
let count = m.get(e);
count = count == undefined ? 0 : count;
if (count != undefined && count >= 1) {
signHashList[i] = getRandomHash();
}
m.set(e, count + 1);
});
return {
psbtStr: psbtStr,
signHashList: signHashList,
};
}
exports.generateMPCUnsignedPSBT = generateMPCUnsignedPSBT;
function getRandomHash() {
const h = (0, crypto_1.sha256)((0, crypto_2.randomBytes)(32));
const s = crypto_lib_1.base.toHex(h.slice(0, 28));
return "ffffffff" + s;
}
function generateMPCSignedPSBT(psbtStr, pubKeyHex, signatureList, network) {
const psbt = getPsbtFromString(psbtStr, network);
const publicKey = crypto_lib_1.base.fromHex(pubKeyHex);
let sighashType = bitcoinjs_lib_1.Transaction.SIGHASH_ALL;
const res = generateMPCUnsignedPSBT(psbtStr, pubKeyHex, network);
const signHashList = res.signHashList;
for (let i = 0; i < psbt.inputCount; i++) {
if (signHashList[i].slice(0, 8) == "ffffffff") {
continue;
}
if (psbt.data.inputs[i].sighashType != undefined) {
sighashType = psbt.data.inputs[i].sighashType;
}
const partialSig = [
{
pubkey: publicKey,
signature: bscript.signature.encode(crypto_lib_1.base.fromHex(signatureList[i]), sighashType),
},
];
try {
psbt.data.updateInput(i, { partialSig });
}
catch (e) {
}
}
return psbt.toHex();
}
exports.generateMPCSignedPSBT = generateMPCSignedPSBT;
function getPsbtFromString(psbtStr, network) {
let psbt;
if (crypto_lib_1.base.isHexString("0x" + psbtStr)) {
psbt = psbt_1.Psbt.fromHex(psbtStr, { network });
}
else {
psbt = psbt_1.Psbt.fromBase64(psbtStr, { network });
}
return psbt;
}
//# sourceMappingURL=psbtSign.js.map

@@ -15,2 +15,13 @@ type utxoInput = {

};
type toSignInput = {
index: number;
address: string;
publicKey?: string;
sighashTypes?: number[];
disableTweakSigner?: boolean;
};
type signPsbtOptions = {
autoFinalized?: boolean;
toSignInputs?: toSignInput[];
};
type Bip32Derivation = {

@@ -75,2 +86,2 @@ masterFingerprint: string;

};
export { utxoInput, utxoOutput, omniOutput, utxoTx, ListingData, BuyingData };
export { utxoInput, utxoOutput, omniOutput, utxoTx, ListingData, BuyingData, signPsbtOptions, toSignInput };
{
"name": "unielon-coin-bitcoin",
"version": "1.0.4",
"version": "1.0.5",
"description": "",

@@ -5,0 +5,0 @@ "main": "./dist/index.js",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc