PHP WebShell

Текущая директория: /opt/BitGoJS/modules/utxo-bin/src

Просмотр файла: generateAddress.ts

import * as assert from 'assert';

import * as utxolib from '@bitgo/utxo-lib';
import { Descriptor } from '@bitgo/wasm-miniscript';

import { Parser } from './Parser';
import { parseUnknown } from './parseUnknown';
import { formatTree } from './format';
import { KeyOptions, getRootWalletKeys } from './args';

function getDefaultChainCodes(): number[] {
  return utxolib.bitgo.chainCodes.filter(
    // these are rare and show an annoying warning in stderr
    (c) => utxolib.bitgo.scriptTypeForChain(c) !== 'p2tr' && utxolib.bitgo.scriptTypeForChain(c) !== 'p2trMusig2'
  );
}

type FixedScriptAddressProperties = {
  chain: utxolib.bitgo.ChainCode;
  index: number;
  type: utxolib.bitgo.outputScripts.ScriptType;
  userPath: string;
  backupPath: string;
  bitgoPath: string;
  userKey: string;
  backupKey: string;
  bitgoKey: string;
  redeemScript?: string;
  witnessScript?: string;
  scriptPubKey: string;
  address: string;
};

const fixedScriptPlaceholders = {
  '%c': 'chain',
  '%i': 'index',
  '%p': 'userPath',
  '%t': 'type',
  '%p0': 'userPath',
  '%p1': 'backupPath',
  '%p2': 'bitgoPath',
  '%k0': 'userKey',
  '%k1': 'backupKey',
  '%k2': 'bitgoKey',
  '%s': 'scriptPubKey',
  '%r': 'redeemScript',
  '%w': 'witnessScript',
  '%a': 'address',
} as const;

export function getAsPlaceholderDescription(v: Record<string, string>): string {
  return Object.entries(v)
    .map(([placeholder, prop]) => `${placeholder} -> ${prop}`)
    .join('\n');
}

export function getFixedScriptAddressPlaceholderDescription(): string {
  return getAsPlaceholderDescription(fixedScriptPlaceholders);
}

function getAddressProperties(
  keys: utxolib.bitgo.RootWalletKeys,
  chain: utxolib.bitgo.ChainCode,
  index: number,
  network: utxolib.Network
): FixedScriptAddressProperties {
  const [userPath, backupPath, bitgoPath] = keys.triple.map((k) => keys.getDerivationPath(k, chain, index));
  const scripts = utxolib.bitgo.getWalletOutputScripts(keys, chain, index);
  const [userKey, backupKey, bitgoKey] = keys.triple.map((k) => k.derivePath(userPath).publicKey.toString('hex'));
  const address = utxolib.address.fromOutputScript(scripts.scriptPubKey, network);
  return {
    chain,
    index,
    type: utxolib.bitgo.scriptTypeForChain(chain),
    userPath,
    backupPath,
    bitgoPath,
    userKey,
    backupKey,
    bitgoKey,
    scriptPubKey: scripts.scriptPubKey.toString('hex'),
    redeemScript: scripts.redeemScript?.toString('hex'),
    witnessScript: scripts.witnessScript?.toString('hex'),
    address,
  };
}

export function formatAddressTree(props: FixedScriptAddressProperties | DescriptorAddressProperties): string {
  const parser = new Parser();
  return formatTree(parseUnknown(parser, 'address', props));
}

export function formatAddressWithFormatString(
  props: Record<string, unknown>,
  placeholders: Record<string, string>,
  format: string
): string {
  // replace all patterns with a % prefix from format string with the corresponding property
  // e.g. %p0 -> userPath, %k1 -> backupKey, etc.
  return format.replace(/%[a-z0-9]+/gi, (match) => {
    if (match in placeholders) {
      const prop = placeholders[match];
      return String(props[prop]);
    }
    return match;
  });
}

export function formatFixedScriptAddress(props: FixedScriptAddressProperties, format: string): string {
  return formatAddressWithFormatString(props, fixedScriptPlaceholders, format);
}

export function getRange(start: number, end: number): number[] {
  return Array.from({ length: end - start + 1 }, (_, i) => start + i);
}

export function parseIndexRange(ranges: string[]): number[] {
  return ranges.flatMap((range) => {
    const [start, end] = range.split('-');
    if (end) {
      return getRange(Number(start), Number(end));
    }
    return [Number(start)];
  });
}

export function* generateFixedScriptAddress(
  argv: KeyOptions & {
    network?: utxolib.Network;
    chain?: number[];
    format: string;
    index: number[];
  }
): Generator<FixedScriptAddressProperties> {
  const rootXpubs = getRootWalletKeys(argv);
  const chains = argv.chain ?? getDefaultChainCodes();
  for (const i of argv.index) {
    for (const chain of chains) {
      assert(utxolib.bitgo.isChainCode(chain));
      // yield formatAddress(rootXpubs, chain, i, argv.network ?? utxolib.networks.bitcoin, argv.format);
      yield getAddressProperties(rootXpubs, chain, i, argv.network ?? utxolib.networks.bitcoin);
    }
  }
}

type DescriptorAddressProperties = {
  descriptor: string;
  index: number;
  explicitScript: string;
  scriptPubKey: string;
  address: string;
};

const descriptorAddressPlaceholders = {
  '%d': 'descriptor',
  '%i': 'index',
  '%e': 'explicitScript',
  '%s': 'scriptPubKey',
  '%a': 'address',
} as const;

export function getDescriptorAddressPlaceholderDescription(): string {
  return getAsPlaceholderDescription(descriptorAddressPlaceholders);
}

export function formatDescriptorAddress(props: DescriptorAddressProperties, format: string): string {
  return formatAddressWithFormatString(props, descriptorAddressPlaceholders, format);
}

export function* generateDescriptorAddress(argv: {
  network: utxolib.Network;
  descriptor: string;
  format: string;
  index: number[];
}): Generator<DescriptorAddressProperties> {
  const descriptor = Descriptor.fromString(argv.descriptor, 'derivable');
  for (const i of argv.index) {
    const derived = descriptor.atDerivationIndex(i);
    const explicitScript = Buffer.from(derived.encode());
    const scriptPubKey = Buffer.from(derived.scriptPubkey());
    const address = utxolib.address.fromOutputScript(scriptPubKey, argv.network);
    yield {
      descriptor: derived.toString(),
      index: i,
      address,
      explicitScript: explicitScript.toString('hex'),
      scriptPubKey: scriptPubKey.toString('hex'),
    };
  }
}

Выполнить команду


Для локальной разработки. Не используйте в интернете!