Unverified Commit 2fc4168b authored by Pavel Ševčík's avatar Pavel Ševčík
Browse files

Rewrote files to Typescript

parent dfa494d3
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var bip47 = require("./payment-code");
exports.fromBuffer = bip47.fromBuffer;
exports.fromBase58 = bip47.fromBase58;
exports.fromWalletSeed = bip47.fromWalletSeed;
exports.utils = require('./utils');
\ No newline at end of file
export { fromBuffer, fromBase58, fromWalletSeed } from "./payment-code";
export * as utils from "./utils";
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const ecc = require('tiny-secp256k1');
const { networks, getP2pkhAddress, sha256 } = require('./utils');
const { fromPublicKey, fromSeed } = require('bip32');
const { encode, decode } = require('bs58check');
const PC_VERSION = 0x47;
class PaymentCode {
constructor(buf, network) {
network = network || networks.bitcoin;
if (buf.length !== 80)
throw new TypeError('Invalid buffer length');
this.version = buf.slice(0, 1);
if (this.version[0] !== 1)
throw new TypeError('Only payment codes version 1 are supported');
this.buf = buf;
this.network = network;
this.root = fromPublicKey(this.pubKey, this.chainCode, this.network);
}
static fromSeed(bSeed, id, network) {
network = network || networks.bitcoin;
const reserved = Buffer.alloc(13, 0);
const root = fromSeed(bSeed);
const coinType = (network.pubKeyHash == networks.bitcoin.pubKeyHash) ? '0' : '1';
const root_bip47 = root.derivePath(`m/47'/${coinType}'/${id}'`);
let pc = Buffer.from('0100', 'hex'); // version + options
pc = Buffer.concat([pc, root_bip47.publicKey]);
pc = Buffer.concat([pc, root_bip47.chainCode]);
if (pc.length !== 67)
throw new TypeError('Missing or wrong publicKey or chainCode');
pc = Buffer.concat([pc, reserved]); // reserved bytes
const pcode = new PaymentCode(pc, network);
pcode.root = root_bip47; // store the privkey
return pcode;
}
get features() {
return this.buf.slice(1, 1);
}
get pubKey() {
return this.buf.slice(2, 2 + 33);
}
get chainCode() {
return this.buf.slice(35, 35 + 32);
}
get paymentCode() {
return this.buf;
}
toBase58() {
const version = Buffer.from([PC_VERSION]);
const buf = Buffer.concat([version, this.buf]);
return encode(buf);
}
_hasPrivKeys() {
return this.root.privateKey != null;
}
derive(index) {
return this.root.derive(index);
}
deriveHardened(index) {
return this.root.deriveHardened(index);
}
getNotificationAddress() {
const child = this.derive(0);
return getP2pkhAddress(child.publicKey, this.network);
}
derivePaymentPrivateKey(A, idx) {
if (!ecc.isPoint(A))
throw new TypeError('Argument is not a valid public key');
const b_node = this.derive(idx);
const b = b_node.privateKey;
const S = ecc.pointMultiply(A, b);
const Sx = S.slice(1, 33);
const s = sha256(Sx);
if (!ecc.isPrivate(s))
throw new TypeError('Invalid shared secret');
return ecc.privateAdd(b, s);
}
derivePaymentPublicKey(a, idx) {
if (!ecc.isPrivate(a) && !ecc.isPoint(a))
throw new TypeError('Argument is neither a valid private key or public key');
let B = null;
let S = null;
if (ecc.isPrivate(a)) {
// a is a private key
B = this.derive(idx).publicKey;
S = ecc.pointMultiply(B, a);
} else if (ecc.isPoint(a)) {
if (!this._hasPrivKeys())
throw new Error('Unable to compute the derivation with a public key provided as argument');
// a is a public key
const A = a;
const b_node = this.derive(idx);
const b = b_node.privateKey;
B = b_node.publicKey;
S = ecc.pointMultiply(A, b);
}
if (!ecc.isPoint(B))
throw new TypeError('Invalid derived public key');
const Sx = S.slice(1, 33);
const s = sha256(Sx);
if (!ecc.isPrivate(s))
throw new TypeError('Invalid shared secret');
return ecc.pointAdd(B, ecc.pointFromScalar(s));
}
getPaymentAddress(a, idx) {
const pubkey = this.derivePaymentPublicKey(a, idx);
return getP2pkhAddress(pubkey, this.network);
}
}
function fromBase58(inString, network) {
const buf = decode(inString);
const version = buf.slice(0, 1);
if (version[0] !== PC_VERSION)
throw new TypeError('Invalid version');
return new PaymentCode(buf.slice(1), network);
}
exports.fromBase58 = fromBase58;
function fromBuffer(buf, network) {
return new PaymentCode(buf, network);
}
exports.fromBuffer = fromBuffer;
function fromWalletSeed(bSeed, id, network) {
return PaymentCode.fromSeed(bSeed, id, network);
}
exports.fromWalletSeed = fromWalletSeed;
import ecc from 'tiny-secp256k1';
import {networks, getP2pkhAddress, sha256, Network} from './utils';
import {BIP32Interface, fromPublicKey, fromSeed} from 'bip32';
import {encode, decode} from 'bs58check';
const PC_VERSION = 0x47;
class PaymentCode {
version: Buffer;
buf: Buffer;
network: Network;
root: BIP32Interface;
constructor(buf: Buffer, network: Network = networks.bitcoin) {
if (buf.length !== 80)
throw new TypeError('Invalid buffer length');
this.version = buf.slice(0, 1);
if (this.version[0] !== 1)
throw new TypeError('Only payment codes version 1 are supported');
this.buf = buf;
this.network = network;
this.root = fromPublicKey(this.pubKey, this.chainCode, this.network);
}
static fromSeed(bSeed: Buffer, id: number | string, network: Network = networks.bitcoin): PaymentCode {
const reserved = Buffer.alloc(13, 0);
const root = fromSeed(bSeed);
const coinType = (network.pubKeyHash === networks.bitcoin.pubKeyHash) ? '0' : '1';
const root_bip47 = root.derivePath(`m/47'/${coinType}'/${id}'`);
let pc = Buffer.from('0100', 'hex'); // version + options
pc = Buffer.concat([pc, root_bip47.publicKey]);
pc = Buffer.concat([pc, root_bip47.chainCode]);
if (pc.length !== 67)
throw new TypeError('Missing or wrong publicKey or chainCode');
pc = Buffer.concat([pc, reserved]); // reserved bytes
const pcode = new PaymentCode(pc, network);
pcode.root = root_bip47; // store the privkey
return pcode;
}
get features(): Buffer {
return this.buf.slice(1, 1);
}
get pubKey(): Buffer {
return this.buf.slice(2, 2 + 33);
}
get chainCode(): Buffer {
return this.buf.slice(35, 35 + 32);
}
get paymentCode(): Buffer {
return this.buf;
}
toBase58(): string {
const version = Buffer.from([PC_VERSION]);
const buf = Buffer.concat([version, this.buf]);
return encode(buf);
}
_hasPrivKeys(): boolean {
return this.root.privateKey != null;
}
derive(index: number): BIP32Interface {
return this.root.derive(index);
}
deriveHardened(index: number): BIP32Interface {
return this.root.deriveHardened(index);
}
getNotificationAddress(): string {
const child = this.derive(0);
return getP2pkhAddress(child.publicKey, this.network);
}
derivePaymentPrivateKey(A: Buffer, idx: number): Buffer {
if (!ecc.isPoint(A))
throw new TypeError('Argument is not a valid public key');
const b_node = this.derive(idx);
if (!b_node.privateKey)
throw new Error("Unable to derive node with private key");
const b = b_node.privateKey;
const S = ecc.pointMultiply(A, b);
if (!S)
throw new Error("Unable to compute resulting point")
const Sx = S.slice(1, 33);
const s = sha256(Sx);
if (!ecc.isPrivate(s))
throw new TypeError('Invalid shared secret');
const paymentPrivateKey = ecc.privateAdd(b, s);
if (!paymentPrivateKey)
throw new TypeError('Unable to compute payment private key');
return paymentPrivateKey;
}
derivePaymentPublicKey(a: Buffer, idx: number): Buffer {
if (!ecc.isPrivate(a) && !ecc.isPoint(a))
throw new TypeError('Argument is neither a valid private key or public key');
let B = null;
let S = null;
if (ecc.isPrivate(a)) {
// a is a private key
B = this.derive(idx).publicKey;
S = ecc.pointMultiply(B, a);
} else if (ecc.isPoint(a)) {
if (!this._hasPrivKeys())
throw new Error('Unable to compute the derivation with a public key provided as argument');
// a is a public key
const A = a;
const b_node = this.derive(idx);
if (!b_node.privateKey)
throw new Error("Unable to derive node with private key");
const b = b_node.privateKey;
B = b_node.publicKey;
S = ecc.pointMultiply(A, b);
}
if (!B || !ecc.isPoint(B))
throw new TypeError('Invalid derived public key');
if (!S)
throw new Error('Unable to compute resulting point');
const Sx = S.slice(1, 33);
const s = sha256(Sx);
if (!ecc.isPrivate(s))
throw new TypeError('Invalid shared secret');
const EccPoint = ecc.pointFromScalar(s);
if (!EccPoint)
throw new Error('Unable to compute point');
const paymentPublicKey = ecc.pointAdd(B, EccPoint);
if (!paymentPublicKey)
throw new TypeError('Unable to compute payment public key');
return paymentPublicKey;
}
getPaymentAddress(a: Buffer, idx: number): string {
const pubkey = this.derivePaymentPublicKey(a, idx);
if (!pubkey)
throw new TypeError('Unable to derive public key')
return getP2pkhAddress(pubkey, this.network);
}
}
export function fromBase58(inString: string, network?: Network): PaymentCode {
const buf = decode(inString);
const version = buf.slice(0, 1);
if (version[0] !== PC_VERSION)
throw new TypeError('Invalid version');
return new PaymentCode(buf.slice(1), network);
}
export function fromBuffer(buf: Buffer, network?: Network) {
return new PaymentCode(buf, network);
}
export function fromWalletSeed(bSeed: Buffer, id: number | string, network?: Network) {
return PaymentCode.fromSeed(bSeed, id, network);
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Buffer = require('safe-buffer').Buffer;
const createHash = require('create-hash');
const bs58check = require('bs58check');
exports.networks = {};
exports.networks.bitcoin = {
messagePrefix: '\x18Bitcoin Signed Message:\n',
bech32: 'bc',
bip32: {
public: 0x0488b21e,
private: 0x0488ade4,
},
pubKeyHash: 0x00,
scriptHash: 0x05,
wif: 0x80,
};
exports.networks.regtest = {
messagePrefix: '\x18Bitcoin Signed Message:\n',
bech32: 'bcrt',
bip32: {
public: 0x043587cf,
private: 0x04358394,
},
pubKeyHash: 0x6f,
scriptHash: 0xc4,
wif: 0xef,
};
exports.networks.testnet = {
messagePrefix: '\x18Bitcoin Signed Message:\n',
bech32: 'tb',
bip32: {
public: 0x043587cf,
private: 0x04358394,
},
pubKeyHash: 0x6f,
scriptHash: 0xc4,
wif: 0xef,
};
function ripemd160(buffer) {
return createHash('rmd160').update(buffer).digest();
}
exports.ripemd160 = ripemd160;
function sha256(buffer) {
return createHash('sha256').update(buffer).digest();
}
exports.sha256 = sha256;
function hash160(buffer) {
return ripemd160(sha256(buffer));
}
exports.hash160 = hash160;
function toBase58Check(hash, version) {
const payload = Buffer.allocUnsafe(21);
payload.writeUInt8(version, 0);
hash.copy(payload, 1);
return bs58check.encode(payload);
}
exports.toBase58Check = toBase58Check;
function getP2pkhAddress(pubkey, network) {
return toBase58Check(hash160(pubkey), network.pubKeyHash)
}
exports.getP2pkhAddress = getP2pkhAddress;
import createHash from 'create-hash';
import bs58check from 'bs58check';
export const networks = {
bitcoin: {
messagePrefix: '\x18Bitcoin Signed Message:\n',
bech32: 'bc',
bip32: {
public: 0x0488b21e,
private: 0x0488ade4,
},
pubKeyHash: 0x00,
scriptHash: 0x05,
wif: 0x80,
},
regtest: {
messagePrefix: '\x18Bitcoin Signed Message:\n',
bech32: 'bcrt',
bip32: {
public: 0x043587cf,
private: 0x04358394,
},
pubKeyHash: 0x6f,
scriptHash: 0xc4,
wif: 0xef,
},
testnet: {
messagePrefix: '\x18Bitcoin Signed Message:\n',
bech32: 'tb',
bip32: {
public: 0x043587cf,
private: 0x04358394,
},
pubKeyHash: 0x6f,
scriptHash: 0xc4,
wif: 0xef,
}
} as const;
export type Network = typeof networks[keyof typeof networks];
export function ripemd160(buffer: Buffer) {
return createHash('rmd160').update(buffer).digest();
}
export function sha256(buffer: Buffer) {
return createHash('sha256').update(buffer).digest();
}
export function hash160(buffer: Buffer) {
return ripemd160(sha256(buffer));
}
export function toBase58Check(hash: Buffer, version: number) {
const payload = Buffer.allocUnsafe(21);
payload.writeUInt8(version, 0);
hash.copy(payload, 1);
return bs58check.encode(payload);
}
export function getP2pkhAddress(pubkey: Buffer, network: Network) {
return toBase58Check(hash160(pubkey), network.pubKeyHash)
}
'use strict'
import assert from 'assert';
import ecc from 'tiny-secp256k1';
import * as bip47 from '../src';
const assert = require('assert')
const ecc = require('tiny-secp256k1');
const bip47 = require('../src')
const utils = bip47.utils
......@@ -82,7 +81,7 @@ describe('payment-code', function() {
const seed = Buffer.from(PC_2.seed, 'hex');
const pc = bip47.fromWalletSeed(seed, 0);
const pc_b58 = pc.toBase58();
assert(pc_b58 == PC_2.pcBase58);
assert(pc_b58 === PC_2.pcBase58);
} catch(e) {
console.log(e)
assert(false);
......@@ -95,11 +94,11 @@ describe('payment-code', function() {
try {
const pc1 = bip47.fromBase58(PC_1.pcBase58);
const pc1_b58 = pc1.toBase58();
assert(pc1_b58 == PC_1.pcBase58);
assert(pc1_b58 === PC_1.pcBase58);
const pc2 = bip47.fromBase58(PC_2.pcBase58);
const pc2_b58 = pc2.toBase58();
assert(pc2_b58 == PC_2.pcBase58);
assert(pc2_b58 === PC_2.pcBase58);
} catch(e) {
assert(false);
}
......@@ -111,11 +110,11 @@ describe('payment-code', function() {
try {
const pc1 = bip47.fromBase58(PC_1.pcBase58);
const notifAddr1 = pc1.getNotificationAddress();
assert(notifAddr1 == PC_1.notifAddr);
assert(notifAddr1 === PC_1.notifAddr);
const pc2 = bip47.fromBase58(PC_2.pcBase58);
const notifAddr2 = pc2.getNotificationAddress();
assert(notifAddr2 == PC_2.notifAddr);
assert(notifAddr2 === PC_2.notifAddr);
} catch(e) {
assert(false);
}
......@@ -176,7 +175,7 @@ describe('payment-code', function() {
const pc2 = bip47.fromWalletSeed(seed, 0);
for (let i=0; i<10; i++) {
const privkeyPayment = pc2.derivePaymentPrivateKey(pubkey1, i);
const strPubkeyPayment = ecc.pointFromScalar(privkeyPayment).toString('hex');
const strPubkeyPayment = ecc.pointFromScalar(privkeyPayment)?.toString('hex');
const strPubkeyPayment2 = pc2.derivePaymentPublicKey(pubkey1, i).toString('hex');
if (strPubkeyPayment !== strPubkeyPayment2)
assert(false);
......@@ -222,4 +221,4 @@ describe('payment-code', function() {
});
});
});
\ No newline at end of file
});
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment