PHP WebShell
Текущая директория: /opt/BitGoJS/node_modules/avalanche/src/utils
Просмотр файла: bintools.ts
/**
* @packageDocumentation
* @module Utils-BinTools
*/
import BN from "bn.js"
import { Buffer } from "buffer/"
import createHash from "create-hash"
import * as bech32 from "bech32"
import { Base58 } from "./base58"
import { Bech32Error, ChecksumError, HexError } from "../utils/errors"
import { utils } from "ethers"
/**
* A class containing tools useful in interacting with binary data cross-platform using
* nodejs & javascript.
*
* This class should never be instantiated directly. Instead,
* invoke the "BinTools.getInstance()" static * function to grab the singleton
* instance of the tools.
*
* Everything in this library uses
* the {@link https://github.com/feross/buffer|feross's Buffer class}.
*
* ```js
* const bintools: BinTools = BinTools.getInstance();
* const b58str: = bintools.bufferToB58(Buffer.from("Wubalubadubdub!"));
* ```
*/
export default class BinTools {
private static instance: BinTools
private constructor() {
this.b58 = Base58.getInstance()
}
private b58: Base58
/**
* Retrieves the BinTools singleton.
*/
static getInstance(): BinTools {
if (!BinTools.instance) {
BinTools.instance = new BinTools()
}
return BinTools.instance
}
/**
* Returns true if base64, otherwise false
* @param str the string to verify is Base64
*/
isBase64(str: string) {
if (str === "" || str.trim() === "") {
return false
}
try {
let b64: Buffer = Buffer.from(str, "base64")
return b64.toString("base64") === str
} catch (err) {
return false
}
}
/**
* Returns true if cb58, otherwise false
* @param cb58 the string to verify is cb58
*/
isCB58(cb58: string): boolean {
return this.isBase58(cb58)
}
/**
* Returns true if base58, otherwise false
* @param base58 the string to verify is base58
*/
isBase58(base58: string): boolean {
if (base58 === "" || base58.trim() === "") {
return false
}
try {
return this.b58.encode(this.b58.decode(base58)) === base58
} catch (err) {
return false
}
}
/**
* Returns true if hexidecimal, otherwise false
* @param hex the string to verify is hexidecimal
*/
isHex(hex: string): boolean {
if (hex === "" || hex.trim() === "") {
return false
}
if (
(hex.startsWith("0x") && hex.slice(2).match(/^[0-9A-Fa-f]/g)) ||
hex.match(/^[0-9A-Fa-f]/g)
) {
return true
} else {
return false
}
}
/**
* Returns true if decimal, otherwise false
* @param str the string to verify is hexidecimal
*/
isDecimal(str: string) {
if (str === "" || str.trim() === "") {
return false
}
try {
return new BN(str, 10).toString(10) === str.trim()
} catch (err) {
return false
}
}
/**
* Returns true if meets requirements to parse as an address as Bech32 on X-Chain or P-Chain, otherwise false
* @param address the string to verify is address
*/
isPrimaryBechAddress = (address: string): boolean => {
const parts: string[] = address.trim().split("-")
if (parts.length !== 2) {
return false
}
try {
bech32.bech32.fromWords(bech32.bech32.decode(parts[1]).words)
} catch (err) {
return false
}
return true
}
/**
* Produces a string from a {@link https://github.com/feross/buffer|Buffer}
* representing a string. ONLY USED IN TRANSACTION FORMATTING, ASSUMED LENGTH IS PREPENDED.
*
* @param buff The {@link https://github.com/feross/buffer|Buffer} to convert to a string
*/
bufferToString = (buff: Buffer): string =>
this.copyFrom(buff, 2).toString("utf8")
/**
* Produces a {@link https://github.com/feross/buffer|Buffer} from a string. ONLY USED IN TRANSACTION FORMATTING, LENGTH IS PREPENDED.
*
* @param str The string to convert to a {@link https://github.com/feross/buffer|Buffer}
*/
stringToBuffer = (str: string): Buffer => {
const buff: Buffer = Buffer.alloc(2 + str.length)
buff.writeUInt16BE(str.length, 0)
buff.write(str, 2, str.length, "utf8")
return buff
}
/**
* Makes a copy (no reference) of a {@link https://github.com/feross/buffer|Buffer}
* over provided indecies.
*
* @param buff The {@link https://github.com/feross/buffer|Buffer} to copy
* @param start The index to start the copy
* @param end The index to end the copy
*/
copyFrom = (
buff: Buffer,
start: number = 0,
end: number = undefined
): Buffer => {
if (end === undefined) {
end = buff.length
}
return Buffer.from(Uint8Array.prototype.slice.call(buff.slice(start, end)))
}
/**
* Takes a {@link https://github.com/feross/buffer|Buffer} and returns a base-58 string of
* the {@link https://github.com/feross/buffer|Buffer}.
*
* @param buff The {@link https://github.com/feross/buffer|Buffer} to convert to base-58
*/
bufferToB58 = (buff: Buffer): string => this.b58.encode(buff)
/**
* Takes a base-58 string and returns a {@link https://github.com/feross/buffer|Buffer}.
*
* @param b58str The base-58 string to convert
* to a {@link https://github.com/feross/buffer|Buffer}
*/
b58ToBuffer = (b58str: string): Buffer => this.b58.decode(b58str)
/**
* Takes a {@link https://github.com/feross/buffer|Buffer} and returns an ArrayBuffer.
*
* @param buff The {@link https://github.com/feross/buffer|Buffer} to
* convert to an ArrayBuffer
*/
fromBufferToArrayBuffer = (buff: Buffer): ArrayBuffer => {
const ab = new ArrayBuffer(buff.length)
const view = new Uint8Array(ab)
for (let i: number = 0; i < buff.length; ++i) {
view[`${i}`] = buff[`${i}`]
}
return view
}
/**
* Takes an ArrayBuffer and converts it to a {@link https://github.com/feross/buffer|Buffer}.
*
* @param ab The ArrayBuffer to convert to a {@link https://github.com/feross/buffer|Buffer}
*/
fromArrayBufferToBuffer = (ab: ArrayBuffer): Buffer => {
const buf = Buffer.alloc(ab.byteLength)
for (let i: number = 0; i < ab.byteLength; ++i) {
buf[`${i}`] = ab[`${i}`]
}
return buf
}
/**
* Takes a {@link https://github.com/feross/buffer|Buffer} and converts it
* to a {@link https://github.com/indutny/bn.js/|BN}.
*
* @param buff The {@link https://github.com/feross/buffer|Buffer} to convert
* to a {@link https://github.com/indutny/bn.js/|BN}
*/
fromBufferToBN = (buff: Buffer): BN => {
if (typeof buff === "undefined") {
return undefined
}
return new BN(buff.toString("hex"), 16, "be")
}
/**
* Takes a {@link https://github.com/indutny/bn.js/|BN} and converts it
* to a {@link https://github.com/feross/buffer|Buffer}.
*
* @param bn The {@link https://github.com/indutny/bn.js/|BN} to convert
* to a {@link https://github.com/feross/buffer|Buffer}
* @param length The zero-padded length of the {@link https://github.com/feross/buffer|Buffer}
*/
fromBNToBuffer = (bn: BN, length?: number): Buffer => {
if (typeof bn === "undefined") {
return undefined
}
const newarr = bn.toArray("be")
/**
* CKC: Still unsure why bn.toArray with a "be" and a length do not work right. Bug?
*/
if (length) {
// bn toArray with the length parameter doesn't work correctly, need this.
const x = length - newarr.length
for (let i: number = 0; i < x; i++) {
newarr.unshift(0)
}
}
return Buffer.from(newarr)
}
/**
* Takes a {@link https://github.com/feross/buffer|Buffer} and adds a checksum, returning
* a {@link https://github.com/feross/buffer|Buffer} with the 4-byte checksum appended.
*
* @param buff The {@link https://github.com/feross/buffer|Buffer} to append a checksum
*/
addChecksum = (buff: Buffer): Buffer => {
const hashslice: Buffer = Buffer.from(
createHash("sha256").update(buff).digest().slice(28)
)
return Buffer.concat([buff, hashslice])
}
/**
* Takes a {@link https://github.com/feross/buffer|Buffer} with an appended 4-byte checksum
* and returns true if the checksum is valid, otherwise false.
*
* @param b The {@link https://github.com/feross/buffer|Buffer} to validate the checksum
*/
validateChecksum = (buff: Buffer): boolean => {
const checkslice: Buffer = buff.slice(buff.length - 4)
const hashslice: Buffer = Buffer.from(
createHash("sha256")
.update(buff.slice(0, buff.length - 4))
.digest()
.slice(28)
)
return checkslice.toString("hex") === hashslice.toString("hex")
}
/**
* Takes a {@link https://github.com/feross/buffer|Buffer} and returns a base-58 string with
* checksum as per the cb58 standard.
*
* @param bytes A {@link https://github.com/feross/buffer|Buffer} to serialize
*
* @returns A serialized base-58 string of the Buffer.
*/
cb58Encode = (bytes: Buffer): string => {
const x: Buffer = this.addChecksum(bytes)
return this.bufferToB58(x)
}
/**
* Takes a cb58 serialized {@link https://github.com/feross/buffer|Buffer} or base-58 string
* and returns a {@link https://github.com/feross/buffer|Buffer} of the original data. Throws on error.
*
* @param bytes A cb58 serialized {@link https://github.com/feross/buffer|Buffer} or base-58 string
*/
cb58Decode = (bytes: Buffer | string): Buffer => {
if (typeof bytes === "string") {
bytes = this.b58ToBuffer(bytes)
}
if (this.validateChecksum(bytes)) {
return this.copyFrom(bytes, 0, bytes.length - 4)
}
throw new ChecksumError("Error - BinTools.cb58Decode: invalid checksum")
}
cb58DecodeWithChecksum = (bytes: Buffer | string): string => {
if (typeof bytes === "string") {
bytes = this.b58ToBuffer(bytes)
}
if (this.validateChecksum(bytes)) {
return `0x${this.copyFrom(bytes, 0, bytes.length).toString("hex")}`
}
throw new ChecksumError("Error - BinTools.cb58Decode: invalid checksum")
}
addressToString = (hrp: string, chainid: string, bytes: Buffer): string =>
`${chainid}-${bech32.bech32.encode(hrp, bech32.bech32.toWords(bytes))}`
stringToAddress = (address: string, hrp?: string): Buffer => {
if (address.substring(0, 2) === "0x") {
// ETH-style address
if (utils.isAddress(address)) {
return Buffer.from(address.substring(2), "hex")
} else {
throw new HexError("Error - Invalid address")
}
}
// Bech32 addresses
const parts: string[] = address.trim().split("-")
if (parts.length < 2) {
throw new Bech32Error("Error - Valid address should include -")
}
if (parts[0].length < 1) {
throw new Bech32Error("Error - Valid address must have prefix before -")
}
const split: number = parts[1].lastIndexOf("1")
if (split < 0) {
throw new Bech32Error("Error - Valid address must include separator (1)")
}
const humanReadablePart: string = parts[1].slice(0, split)
if (humanReadablePart.length < 1) {
throw new Bech32Error("Error - HRP should be at least 1 character")
}
if (
humanReadablePart !== "avax" &&
humanReadablePart !== "fuji" &&
humanReadablePart != "local" &&
humanReadablePart != "custom" &&
humanReadablePart != hrp
) {
throw new Bech32Error("Error - Invalid HRP")
}
return Buffer.from(
bech32.bech32.fromWords(bech32.bech32.decode(parts[1]).words)
)
}
/**
* Takes an address and returns its {@link https://github.com/feross/buffer|Buffer}
* representation if valid. A more strict version of stringToAddress.
*
* @param addr A string representation of the address
* @param blockchainID A cb58 encoded string representation of the blockchainID
* @param alias A chainID alias, if any, that the address can also parse from.
* @param addrlen VMs can use any addressing scheme that they like, so this is the appropriate number of address bytes. Default 20.
*
* @returns A {@link https://github.com/feross/buffer|Buffer} for the address if valid,
* undefined if not valid.
*/
parseAddress = (
addr: string,
blockchainID: string,
alias: string = undefined,
addrlen: number = 20
): Buffer => {
const abc: string[] = addr.split("-")
if (
abc.length === 2 &&
((alias && abc[0] === alias) || (blockchainID && abc[0] === blockchainID))
) {
const addrbuff = this.stringToAddress(addr)
if ((addrlen && addrbuff.length === addrlen) || !addrlen) {
return addrbuff
}
}
return undefined
}
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!