@dojima-wallet/connection
Version:
Initialise and connection for layer 1&2 blockchain
126 lines (119 loc) • 3.62 kB
text/typescript
import { bech32 } from "bech32";
import crypto from "crypto";
import hexEncoding from "crypto-js/enc-hex";
import ripemd160 from "crypto-js/ripemd160";
import sha256 from "crypto-js/sha256";
/**
* Convert string to bytes.
*
* @param {string} string
* @returns {number[]} The bytes from the given string.
*/
export const getBytes = (string: string): number[] => {
const arrayBytes: number[] = [];
const buffer = Buffer.from(string, "utf16le");
for (let i = 0; i < buffer.length; i++) {
arrayBytes.push(buffer[i]);
}
return arrayBytes;
};
/**
* Convert Buffer to hex string.
*
* @param {Buffer} arr
* @returns {string} The hex string from the given buffer.
*/
export const ab2hexstring = (arr: Buffer) => {
let result = "";
for (let i = 0; i < arr.length; i++) {
let str = arr[i].toString(16);
str = str.length === 0 ? "00" : str.length === 1 ? "0" + str : str;
result += str;
}
return result;
};
/**
* Calculate `ripemd160(sha256(hex))` from the hex string
*
* @param {string} hex The hex encoded string.
* @returns {string} The hex string from the given buffer.
*
* @throws {"sha256ripemd160 expects a string"} Thrown if non-string is provided.
* @throws {"invalid hex string length"} Thrown if the given hex string is an invalid one.
*/
export const sha256ripemd160 = (hex: string): string => {
if (typeof hex !== "string")
throw new Error("sha256ripemd160 expects a string");
if (hex.length % 2 !== 0)
throw new Error(`invalid hex string length: ${hex}`);
const hexEncoded = hexEncoding.parse(hex);
const ProgramSha256 = sha256(hexEncoded);
return ripemd160(ProgramSha256).toString();
};
/**
* Encode address from the string or Buffer.
*
* @param {string|Buffer} value The string or Buffer to be encoded.
* @param {string} prefix The prefix of the address. (optional)
* @param {BufferEncoding} type The buffer encoding type. It will be used when string is provided. (optional)
* @returns {string} The address generated from the given string or buffer.
*/
export const encodeAddress = (
value: string | Buffer,
prefix = "dojima",
type: BufferEncoding = "hex"
): string => {
let words;
if (Buffer.isBuffer(value)) {
words = bech32.toWords(Buffer.from(value));
} else {
words = bech32.toWords(Buffer.from(value, type));
}
return bech32.encode(prefix, words);
};
/**
* Create address from the public key.
*
* @param {Buffer} publicKey The public key in Buffer format.
* @returns {string} The address generated from the given public key(buffer format).
*/
export const createAddress = (publicKey: Buffer): string => {
const hexed = ab2hexstring(publicKey);
const hash = sha256ripemd160(hexed);
const address = encodeAddress(hash, "dojima");
return address;
};
/**
* Calculate pbkdf2 (Password-Based Key Derivation Function 2).
*
* @param {string|Buffer|Array|DataView} passphrase.
* @param {string|Buffer|Array|DataView} salt
* @param {number} iterations
* @param {number} keylen
* @param {string} digest
* @returns {Buffer} The pbkdf2 value from the given options.
*/
export const pbkdf2Async = async (
passphrase: string | Buffer | NodeJS.TypedArray | DataView,
salt: string | Buffer | NodeJS.TypedArray | DataView,
iterations: number,
keylen: number,
digest: string
): Promise<Buffer> => {
return new Promise<Buffer>((resolve, reject) => {
crypto.pbkdf2(
passphrase,
salt,
iterations,
keylen,
digest,
(err, drived) => {
if (err) {
reject(err);
} else {
resolve(drived);
}
}
);
});
};