sendover
Version:
Tools for creating and paying invoices privately on Bitcoin SV
171 lines • 7.99 kB
JavaScript
;
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