send-crypto
Version:
A minimal JavaScript library / wallet for sending crypto assets
216 lines • 19.5 kB
JavaScript
import BigNumber from "bignumber.js";
import { BCHHandler } from "./handlers/BCH/BCHHandler";
import { BTCHandler } from "./handlers/BTC/BTCHandler";
import { ERC20Handler } from "./handlers/ERC20/ERC20Handler";
import { ETHHandler } from "./handlers/ETH/ETHHandler";
import { FILHandler } from "./handlers/FIL/FILHandler";
import { LTCHandler } from "./handlers/LTC/LTCHandler";
import { TERRAHandler } from "./handlers/TERRA/TERRAHandler";
import { ZECHandler } from "./handlers/ZEC/ZECHandler";
import { strip0x, toHex } from "./lib/utils";
export default class CryptoAccount {
handlers = [];
privateKey;
network;
defaultAsset;
constructorOptions;
sharedState;
constructor(privateKey, options) {
this.privateKey = strip0x(privateKey instanceof Uint8Array ? toHex(privateKey) : privateKey);
this.network = (options && options.network) || "mainnet";
this.constructorOptions = options;
this.sharedState = {};
this.registerHandler(BTCHandler, 0);
this.registerHandler(ZECHandler, 10);
this.registerHandler(BCHHandler, 20);
this.registerHandler(ETHHandler, 30);
this.registerHandler(FILHandler, 40);
this.registerHandler(TERRAHandler, 50);
this.registerHandler(ERC20Handler, 60);
this.registerHandler(LTCHandler, 60);
if (options && options.extraHandlers) {
for (const handler of options.extraHandlers) {
this.registerHandler(handler);
}
}
this.defaultAsset = options && options.defaultAsset;
}
registerHandler = (handlerClass, priorityIn) => {
const priority = priorityIn === undefined
? this.handlers.length === 0
? 0
: this.handlers[this.handlers.length - 1].priority
: priorityIn;
const lastPosition = this.handlers.reduce((index, item, currentIndex) => item.priority <= priority ? currentIndex + 1 : index, 0);
this.handlers.splice(lastPosition, 0, {
handler: new handlerClass(this.privateKey, this.network, this.constructorOptions, this.sharedState),
priority,
});
};
address = async (assetIn, options) => {
const asset = assetIn || this.defaultAsset;
if (!asset) {
throw new Error(`Must provide an asset`);
}
return this.deferHandler().address(asset, options);
};
getBalance = async (assetIn, options) => {
const asset = assetIn || this.defaultAsset;
if (!asset) {
throw new Error(`Must provide an asset`);
}
const bn = await this.deferHandler().getBalance(asset, options);
return (options && options.bn ? new options.bn(bn.toFixed()) : bn.toNumber());
};
// tslint:disable-next-line: member-ordering
balanceOf = this.getBalance;
getBalanceInSats = async (assetIn, options) => {
const asset = assetIn || this.defaultAsset;
if (!asset) {
throw new Error(`Must provide an asset`);
}
const bn = await this.deferHandler().getBalanceInSats(asset, options);
return (options && options.bn ? new options.bn(bn.toFixed()) : bn.toNumber());
};
// tslint:disable-next-line: member-ordering
balanceOfInSats = this.getBalanceInSats;
send = (to, value, assetIn, options) => {
const asset = assetIn || this.defaultAsset;
if (!asset) {
throw new Error(`Must provide an asset`);
}
return this.deferHandler().send(to, new BigNumber(value.toString()), asset, options);
};
sendSats = (to, value, assetIn, options) => {
const asset = assetIn || this.defaultAsset;
if (!asset) {
throw new Error(`Must provide an asset`);
}
return this.deferHandler().sendSats(to, new BigNumber(value.toString()), asset, options);
};
deferHandler = (thisHandler) => {
return {
address: (deferredAsset, deferredOptions) => {
const nextHandler = this.findHandler(deferredAsset, thisHandler);
if (nextHandler.address) {
return nextHandler.address(deferredAsset, deferredOptions || {}, this.deferHandler(nextHandler));
}
else {
return this.deferHandler(nextHandler).address(deferredAsset, deferredOptions);
}
},
getBalance: (deferredAsset, deferredOptions) => {
const nextHandler = this.findHandler(deferredAsset, thisHandler);
if (nextHandler.getBalance) {
return nextHandler.getBalance(deferredAsset, deferredOptions || {}, this.deferHandler(nextHandler));
}
else {
return this.deferHandler(nextHandler).getBalance(deferredAsset, deferredOptions);
}
},
getBalanceInSats: (deferredAsset, deferredOptions) => {
const nextHandler = this.findHandler(deferredAsset, thisHandler);
if (nextHandler.getBalanceInSats) {
return nextHandler.getBalanceInSats(deferredAsset, deferredOptions || {}, this.deferHandler(nextHandler));
}
else {
return this.deferHandler(nextHandler).getBalanceInSats(deferredAsset, deferredOptions);
}
},
send: (deferredTo, deferredValue, deferredAsset, deferredOptions) => {
const nextHandler = this.findHandler(deferredAsset, thisHandler);
if (nextHandler.send) {
return nextHandler.send(deferredTo, deferredValue, deferredAsset, deferredOptions || {}, this.deferHandler(nextHandler));
}
else {
return this.deferHandler(nextHandler).send(deferredTo, deferredValue, deferredAsset, deferredOptions);
}
},
sendSats: (deferredTo, deferredValue, deferredAsset, deferredOptions) => {
const nextHandler = this.findHandler(deferredAsset, thisHandler);
if (nextHandler.sendSats) {
return nextHandler.sendSats(deferredTo, deferredValue, deferredAsset, deferredOptions || {}, this.deferHandler(nextHandler));
}
else {
return this.deferHandler(nextHandler).sendSats(deferredTo, deferredValue, deferredAsset, deferredOptions);
}
},
};
};
findHandler = (asset, from) => {
const fromIndex = from
? this.handlers.findIndex((i) => i.handler === from)
: -1;
for (let i = (fromIndex === -1 ? this.handlers.length : fromIndex) - 1; i >= 0; i--) {
const handler = this.handlers[i].handler;
// console.log(handler);
if (handler.handlesAsset(asset)) {
return handler;
}
}
let assetString;
try {
assetString = JSON.stringify(asset);
}
catch (error) {
assetString = (asset && asset.name) || asset;
}
throw new Error(`Unsupported asset ${assetString}`);
};
}
export const newPrivateKey = () => {
// @ts-ignore
try {
// @ts-ignore
const array = new Uint8Array(32);
// @ts-ignore
window.crypto.getRandomValues(array);
return toHex(array);
}
catch (error) {
// Ignore window error.
}
return require("crypto").randomBytes(32).toString("hex");
};
CryptoAccount.newPrivateKey = newPrivateKey;
////////////////////////////////////////////////////////////////////////////////
// EXPORTS //
// Based on https://github.com/MikeMcl/bignumber.js/blob/master/bignumber.js //
////////////////////////////////////////////////////////////////////////////////
// tslint:disable: no-object-mutation
// tslint:disable-next-line: no-string-literal
CryptoAccount.default = CryptoAccount.CryptoAccount =
CryptoAccount;
// AMD
try {
// @ts-ignore
if (typeof define === "function" && define.amd) {
// @ts-ignore
define(() => CryptoAccount);
}
}
catch (error) {
/* ignore */
}
// Node.js and other environments that support module.exports.
try {
// @ts-ignore
if (typeof module !== "undefined" && module.exports) {
module.exports = CryptoAccount;
}
}
catch (error) {
/* ignore */
}
// Browser.
try {
// @ts-ignore
if (typeof window !== "undefined" && window) {
// @ts-ignore
window.CryptoAccount = CryptoAccount;
}
}
catch (error) {
/* ignore */
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxTQUFTLE1BQU0sY0FBYyxDQUFDO0FBRXJDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdkQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzdELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdkQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUM3RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFdkQsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFpQjdDLE1BQU0sQ0FBQyxPQUFPLE9BQU8sYUFBYTtJQUNiLFFBQVEsR0FHcEIsRUFBRSxDQUFDO0lBQ1MsVUFBVSxDQUFTO0lBQ25CLE9BQU8sQ0FBUztJQUNoQixZQUFZLENBQW9CO0lBQ2hDLGtCQUFrQixDQUFpQztJQUU1RCxXQUFXLENBQU07SUFFekIsWUFDSSxVQUErQixFQUMvQixPQUFxRDtRQUVyRCxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FDckIsVUFBVSxZQUFZLFVBQVUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQ3BFLENBQUM7UUFDRixJQUFJLENBQUMsT0FBTyxHQUFHLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxTQUFTLENBQUM7UUFDekQsSUFB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