UNPKG

sendover

Version:

Tools for creating and paying invoices privately on Bitcoin SV

171 lines 7.99 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getPaymentAddressString = exports.getPaymentPubKeyString = exports.getPaymentPubKey = exports.computePaymentContext = exports.getPaymentAddress = void 0; /* eslint-disable @typescript-eslint/no-explicit-any */ const sdk_1 = require("@bsv/sdk"); const babbage_bsv_1 = __importDefault(require("babbage-bsv")); const BN = babbage_bsv_1.default.crypto.BN; const HashJs = babbage_bsv_1.default.crypto.Hash; const G = babbage_bsv_1.default.crypto.Point.getG(); const sharedSecretCache_1 = __importDefault(require("./sharedSecretCache")); const _1 = require("."); /** * Returns a payment address for use by the sender, given the recipient's public key, the sender's private key and the invoice number. * * @param params All parameters are provided in an object * @param params.senderPrivateKey The private key of the sender in WIF format * @param params.recipientPublicKey The public key of the recipient in hexadecimal DER format * @param params.invoiceNumber The invoice number to use * @param params.revealCounterpartyLinkage=false When true, reveals the root shared secret between the two counterparties rather than performing key derivation, returning it as a hex string * @param params.revealPaymentLinkage=false When true, reveals the secret between the two counterparties used for this specific invoice number, rather than performing key derivation. Returns the linkage as a hex string * @param params.returnType=address] The destination key return type, either `address` or `publicKey` * * @returns The destination address or public key */ function getPaymentAddress(params) { // First, a shared secret is calculated based on the public and private keys. let publicKey, privateKey; let cacheKey; if (typeof params.recipientPublicKey === 'string') { cacheKey = `-${params.recipientPublicKey}`; publicKey = babbage_bsv_1.default.PublicKey.fromString(params.recipientPublicKey); } else if (params.recipientPublicKey instanceof babbage_bsv_1.default.PublicKey) { cacheKey = `-${params.recipientPublicKey.toString()}`; publicKey = params.recipientPublicKey; } else { throw new Error('Unrecognized format for recipientPublicKey'); } if (typeof params.senderPrivateKey === 'string') { cacheKey = params.senderPrivateKey + cacheKey; privateKey = BN.fromHex(params.senderPrivateKey); } else if (params.senderPrivateKey instanceof BN) { cacheKey = params.senderPrivateKey.toHex({ size: 32 }) + cacheKey; privateKey = params.senderPrivateKey; } else if (params.senderPrivateKey instanceof babbage_bsv_1.default.PrivateKey) { cacheKey = params.senderPrivateKey.bn.toHex({ size: 32 }) + cacheKey; privateKey = params.senderPrivateKey.bn; } else { throw new Error('Unrecognized format for senderPrivateKey'); } let sharedSecret; if (sharedSecretCache_1.default[cacheKey]) { sharedSecret = sharedSecretCache_1.default[cacheKey]; } else { sharedSecret = publicKey.point.mul(privateKey).toBuffer(); sharedSecretCache_1.default[cacheKey] = sharedSecret; } if (params.revealCounterpartyLinkage === true) { return sharedSecret.toString('hex'); } // The invoice number is turned into a buffer. const invoiceNumber = Buffer.from(String(params.invoiceNumber), 'utf8'); // An HMAC is calculated with the shared secret and the invoice number. const hmac = HashJs.sha256hmac(invoiceNumber, sharedSecret); if (params.revealPaymentLinkage === true) { return hmac.toString('hex'); } // The HMAC is multiplied by the generator point. const point = G.mul(BN.fromBuffer(hmac)); // The resulting point is added to the recipient public key. const finalPublicKey = babbage_bsv_1.default.PublicKey.fromPoint(publicKey.point.add(point)); // Finally, an address is calculated with the new public key. if (params.returnType === undefined || params.returnType === 'address') { return babbage_bsv_1.default.Address.fromPublicKey(finalPublicKey).toString(); } else if (params.returnType === 'publicKey') { return finalPublicKey.toString(); } else if (params.returnType === 'babbage-bsv') { return finalPublicKey; } else { throw new Error('The return type must either be "address" or "publicKey"'); } } exports.getPaymentAddress = getPaymentAddress; function computePaymentContext(params) { // First, a shared secret is calculated based on the public and private keys. let publicKey; if (typeof params.recipientPublicKey === 'string') { publicKey = sdk_1.PublicKey.fromString(params.recipientPublicKey); } else if (params.recipientPublicKey instanceof sdk_1.PublicKey) { publicKey = params.recipientPublicKey; } else { throw new Error('Unrecognized format for recipientPublicKey'); } let privateKey; if (typeof params.senderPrivateKey === 'string') { privateKey = sdk_1.PrivateKey.fromString(params.senderPrivateKey, 'hex'); } else if (params.senderPrivateKey instanceof sdk_1.PrivateKey) { privateKey = params.senderPrivateKey; } else if (params.senderPrivateKey instanceof sdk_1.BigNumber) { privateKey = params.senderPrivateKey; } else { throw new Error('Unrecognized format for senderPrivateKey'); } const sharedSecret = publicKey.mul(privateKey).encode(true); // The invoice number is turned into a buffer. const invoiceBuffer = (0, _1.asArray)(String(params.invoiceNumber), 'utf8'); // An HMAC is calculated with the shared secret and the invoice number. const hmac = sdk_1.Hash.sha256hmac(sharedSecret, invoiceBuffer); const curve = new sdk_1.Curve(); // The HMAC is multiplied by the generator point. const point = curve.g.mul(new sdk_1.BigNumber(hmac)); // The resulting point is added to the recipient public key. const resultPublicKey = new sdk_1.PublicKey(publicKey.add(point)); return { publicKey: resultPublicKey, sharedSecret, hmac }; } exports.computePaymentContext = computePaymentContext; /** * @param params All parameters are provided in an object * @param params.senderPrivateKey The private key of the sender in WIF format * @param params.recipientPublicKey The public key of the recipient in hexadecimal DER format * @param params.invoiceNumber The invoice number to use * * @returns The destination public key */ function getPaymentPubKey(params) { const { publicKey } = computePaymentContext(params); return publicKey; } exports.getPaymentPubKey = getPaymentPubKey; /** * @param params All parameters are provided in an object * @param params.senderPrivateKey The private key of the sender in WIF format * @param params.recipientPublicKey The public key of the recipient in hexadecimal DER format * @param params.invoiceNumber The invoice number to use * * @returns The destination public key Base58 string */ function getPaymentPubKeyString(params) { return getPaymentPubKey(params).toString(); } exports.getPaymentPubKeyString = getPaymentPubKeyString; /** * @param params All parameters are provided in an object * @param params.senderPrivateKey The private key of the sender in WIF format * @param params.recipientPublicKey The public key of the recipient in hexadecimal DER format * @param params.invoiceNumber The invoice number to use * * @returns The destination address as Base58 string */ function getPaymentAddressString(params) { const pubKey = getPaymentPubKey(params); return pubKey.toAddress(); } exports.getPaymentAddressString = getPaymentAddressString; //# sourceMappingURL=getPaymentAddress.js.map