PHP WebShell
Текущая директория: /opt/BitGoJS/modules/utxo-lib/test/integration_local_rpc/generate
Просмотр файла: RpcClient.ts
import * as assert from 'assert';
import axios, { AxiosError } from 'axios';
import buildDebug from 'debug';
import { Network, getMainnet, getNetworkName, isZcash } from '../../../src/networks';
import { RpcTransaction } from './RpcTypes';
const utxolib = require('../../../src');
const debug = buildDebug('RpcClient');
function sleep(millis: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, millis);
});
}
export class RpcError extends Error {
constructor(public rpcError: { code: number; message: string }) {
super(`RPC error: ${rpcError.message} (code=${rpcError.code})`);
}
static isRpcErrorWithCode(e: Error, code: number): boolean {
return e instanceof RpcError && e.rpcError.code === code;
}
}
type NetworkInfo = { subversion: string };
const BITCOIN_CORE_22_99 = '/Satoshi:22.99.0/';
export class RpcClient {
id = 0;
constructor(protected network: Network, protected url: string, protected networkInfo?: NetworkInfo) {}
/**
* Poor man's Bluebird.map(arr, f, { concurrency })
* Processes promises in batches of 16
*
* @param arr
* @param f
* @param [concurrency=8]
*/
static async parallelMap<S, T>(
arr: S[],
f: (S, i: number) => Promise<T>,
{ concurrency }: { concurrency: number } = { concurrency: 16 }
): Promise<T[]> {
const rest: S[] = arr.splice(concurrency);
const result = await Promise.all(arr.map((v, i) => f(v, i)));
if (rest.length) {
return [...result, ...(await this.parallelMap(rest, f))];
}
return result;
}
protected getUrl(): string {
return this.url;
}
async exec<T>(method: string, ...params: unknown[]): Promise<T> {
try {
debug('>', this.getUrl(), method, params);
const response = await axios.post(this.getUrl(), {
jsonrpc: '1.0',
method,
params,
id: `${this.id++}`,
});
if (method === 'generate' || method === 'generatetoaddress') {
debug('<', '[...]');
} else {
debug('<', response.data.result);
}
return response.data.result;
} catch (e) {
if (e.isAxiosError && e.response) {
e = e as AxiosError;
debug('< ERROR', e.response.statusText, e.response.data);
e = e as AxiosError;
const { error = {} } = e.response.data;
throw new RpcError(error);
}
throw e;
}
}
requiresWalletPath(): boolean {
if (!this.networkInfo) {
throw new Error(`networkInfo must be set`);
}
return this.networkInfo.subversion === BITCOIN_CORE_22_99;
}
withWallet(walletName: string): RpcClientWithWallet {
if (!this.networkInfo) {
throw new Error(`networkInfo must be set`);
}
return new RpcClientWithWallet(this.network, this.url, this.networkInfo, walletName);
}
async getHelp(): Promise<string> {
return this.exec('help');
}
async createWallet(walletName: string): Promise<string> {
return this.exec('createwallet', walletName);
}
async loadWallet(walletName: string): Promise<string> {
return this.exec('loadwallet', walletName);
}
async getNetworkInfo(): Promise<{ subversion: string }> {
return this.exec('getnetworkinfo');
}
async getBlockCount(): Promise<number> {
return this.exec('getblockcount');
}
async getRawTransaction(txid: string): Promise<Buffer> {
return Buffer.from(await this.exec<string>('getrawtransaction', txid), 'hex');
}
async getRawTransactionVerbose(txid: string): Promise<RpcTransaction> {
const verbose = isZcash(this.network) ? 1 : true;
return await this.exec('getrawtransaction', txid, verbose);
}
async sendRawTransaction(tx: Buffer): Promise<string> {
return await this.exec('sendrawtransaction', tx.toString('hex'));
}
static async fromEnvvar(network: Network): Promise<RpcClient> {
const networkName = getNetworkName(network);
assert(networkName);
const envKey = 'RPC_' + networkName.toUpperCase();
const url = process.env[envKey];
if (url === undefined) {
throw new Error(`envvar ${envKey} not set`);
}
return this.forUrl(network, url);
}
static getSupportedNodeVersions(network: Network): string[] {
switch (getMainnet(network)) {
case utxolib.networks.bitcoin:
return ['/Satoshi:0.20.0/', '/Satoshi:0.21.1/', '/Satoshi:22.0.0/', BITCOIN_CORE_22_99];
case utxolib.networks.bitcoincash:
return ['/Bitcoin Cash Node:23.0.0(EB32.0)/'];
case utxolib.networks.bitcoinsv:
return ['/Bitcoin SV:1.0.5/'];
case utxolib.networks.bitcoingold:
return ['/Bitcoin Gold:0.17.3/'];
case utxolib.networks.dash:
return ['/Dash Core:0.16.1.1/'];
case utxolib.networks.dogecoin:
return ['/Shibetoshi:1.14.5/'];
case utxolib.networks.ecash:
return ['/Bitcoin ABC:0.26.9(EB32.0)/'];
case utxolib.networks.litecoin:
return ['/LitecoinCore:0.17.1/'];
case utxolib.networks.zcash:
return ['/MagicBean:4.7.0/'];
default:
return [];
}
}
static async forUrl(network: Network, url: string): Promise<RpcClient> {
const networkName = getNetworkName(network);
const rpcClient = new RpcClient(network, url);
const networkinfo = await rpcClient.getNetworkInfo();
const versions = this.getSupportedNodeVersions(network);
if (!versions.includes(networkinfo.subversion)) {
throw new Error(`unsupported coin ${networkName} subversion=${networkinfo.subversion} versions=${versions}`);
}
return new RpcClient(network, url, networkinfo);
}
static async forUrlWait(network: Network, url: string): Promise<RpcClient> {
for (let i = 0; i < 600; i++) {
try {
return await this.forUrl(network, url);
} catch (e) {
console.error(`[${getNetworkName(network)}] ${e}, waiting 1000 millis...`);
await sleep(1_000);
}
}
throw new Error(`could not get RpcClient`);
}
}
export class RpcClientWithWallet extends RpcClient {
constructor(network: Network, url: string, networkInfo: NetworkInfo, private walletName?: string) {
super(network, url, networkInfo);
}
protected getUrl(): string {
if (this.requiresWalletPath()) {
return super.getUrl() + '/wallet/' + this.walletName;
}
return super.getUrl();
}
public async getWalletInfo(): Promise<Record<string, unknown>> {
return await this.exec('getwalletinfo');
}
public async getBalance(): Promise<number> {
return await this.exec('getbalance');
}
async getNewAddress(): Promise<string> {
return this.exec('getnewaddress');
}
async sendToAddress(address: string, amount: number | string): Promise<string> {
return this.exec('sendtoaddress', address, amount);
}
async generateToAddress(n: number, address: string): Promise<void> {
switch (this.network) {
case utxolib.networks.zcashTest:
await this.exec('generate', n);
await sleep(1_000);
await this.sendToAddress(address, 1);
break;
default:
await this.exec('generatetoaddress', n, address);
}
}
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!