Skip to content

Commit

Permalink
refactor: use getNetworkOptions(Demand) for network options
Browse files Browse the repository at this point in the history
Gets rid of some boilerplate to convert a string to a network object

Issue: BTC-1351
  • Loading branch information
OttoAllmendinger committed Sep 26, 2024
1 parent 65b1c9a commit d5b73ca
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 28 deletions.
30 changes: 30 additions & 0 deletions modules/utxo-bin/src/args/parseNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,33 @@ export function getNetworkForName(name: string): utxolib.Network {
export function getNetwork(argv: { network: string }): utxolib.Network {
return getNetworkForName(argv.network);
}

type DemandOption<T> = T & { demandOption: true };

type NetworkOption<TDefault> = {
type: 'string';
description: string;
default: TDefault;
coerce: (arg: string) => utxolib.Network;
};

export function getNetworkOptions(defaultValue?: string): {
network: NetworkOption<typeof defaultValue>;
} {
return {
network: {
type: 'string',
description: 'network name',
default: defaultValue,
coerce: getNetworkForName,
},
};
}

export function getNetworkOptionsDemand(defaultValue?: string): {
network: DemandOption<NetworkOption<typeof defaultValue>>;
} {
return {
network: { ...getNetworkOptions(defaultValue).network, demandOption: true },
};
}
43 changes: 15 additions & 28 deletions modules/utxo-bin/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { AddressParser } from './AddressParser';
import { parseUnknown } from './parseUnknown';
import { getParserTxProperties } from './ParserTx';
import { ScriptParser } from './ScriptParser';
import { readStringOptions, argToString, stringToBuffer, getNetwork, getNetworkForName } from './args';
import { readStringOptions, argToString, stringToBuffer, getNetworkOptions, getNetworkOptionsDemand } from './args';
import {
formatAddressTree,
formatAddressWithFormatString,
Expand All @@ -31,7 +31,7 @@ import { parseXpub } from './bip32';
type OutputFormat = 'tree' | 'json';

type ArgsParseTransaction = {
network: string;
network: utxolib.Network;
stdin: boolean;
clipboard: boolean;
path?: string;
Expand All @@ -53,22 +53,22 @@ type ArgsParseTransaction = {
} & Omit<TxParserArgs, 'parseSignatureData'>;

type ArgsParseAddress = {
network?: string;
network?: utxolib.Network;
all: boolean;
format: OutputFormat;
convert: boolean;
address: string;
};

type ArgsParseScript = {
network?: string;
network?: utxolib.Network;
format: OutputFormat;
all: boolean;
script: string;
};

export type ArgsGenerateAddress = {
network?: string;
network: utxolib.Network;
userKey: string;
backupKey: string;
bitgoKey: string;
Expand Down Expand Up @@ -102,17 +102,6 @@ function formatString(parsed: ParserNode, argv: yargs.Arguments<FormatStringArgs
throw new Error(`invalid format ${argv.format}`);
}

function resolveNetwork<T extends { network?: string }>(
args: T
): T & {
network?: utxolib.Network;
} {
if (args.network) {
return { ...args, network: getNetworkForName(args.network) };
}
return { ...args, network: undefined };
}

export function getTxParser(argv: yargs.Arguments<ArgsParseTransaction>): TxParser {
if (argv.all) {
return new TxParser({ ...argv, ...TxParser.PARSE_ALL });
Expand All @@ -128,11 +117,11 @@ export function getTxParser(argv: yargs.Arguments<ArgsParseTransaction>): TxPars
}

export function getAddressParser(argv: ArgsParseAddress): AddressParser {
return new AddressParser(resolveNetwork(argv));
return new AddressParser(argv);
}

export function getScriptParser(argv: ArgsParseScript): ScriptParser {
return new ScriptParser(resolveNetwork(argv));
return new ScriptParser(argv);
}

export const cmdParseTx = {
Expand All @@ -147,14 +136,14 @@ export const cmdParseTx = {
builder(b: yargs.Argv<unknown>): yargs.Argv<ArgsParseTransaction> {
return b
.options(readStringOptions)
.options(getNetworkOptionsDemand())
.option('txid', { type: 'string' })
.option('blockHeight', { type: 'number' })
.option('txIndex', { type: 'number' })
.option('fetchAll', { type: 'boolean', default: false })
.option('fetchStatus', { type: 'boolean', default: false })
.option('fetchInputs', { type: 'boolean', default: false })
.option('fetchSpends', { type: 'boolean', default: false })
.option('network', { alias: 'n', type: 'string', demandOption: true })
.option('parseScriptAsm', { alias: 'scriptasm', type: 'boolean', default: false })
.option('parseScriptData', { alias: 'scriptdata', type: 'boolean', default: false })
.option('parseSignatureData', { alias: 'sigdata', type: 'boolean', default: false })
Expand Down Expand Up @@ -185,7 +174,6 @@ export const cmdParseTx = {
},

async handler(argv: yargs.Arguments<ArgsParseTransaction>): Promise<void> {
const network = getNetwork(argv);
let data;

const httpClient = await getClient({ cache: argv.cache });
Expand All @@ -198,7 +186,7 @@ export const cmdParseTx = {
blockHeight: argv.blockHeight,
txIndex: argv.txIndex,
},
network
argv.network
);
}

Expand All @@ -210,8 +198,8 @@ export const cmdParseTx = {
const bytes = stringToBuffer(string, 'hex');

let tx = utxolib.bitgo.isPsbt(bytes)
? utxolib.bitgo.createPsbtFromBuffer(bytes, network)
: utxolib.bitgo.createTransactionFromBuffer(bytes, network, { amountType: 'bigint' });
? utxolib.bitgo.createPsbtFromBuffer(bytes, argv.network)
: utxolib.bitgo.createTransactionFromBuffer(bytes, argv.network, { amountType: 'bigint' });

const { id: txid } = getParserTxProperties(tx, undefined);
if (tx instanceof utxolib.bitgo.UtxoTransaction) {
Expand All @@ -235,7 +223,7 @@ export const cmdParseTx = {
}

const parsed = getTxParser(argv).parse(tx, {
status: argv.fetchStatus && txid ? await fetchTransactionStatus(httpClient, txid, network) : undefined,
status: argv.fetchStatus && txid ? await fetchTransactionStatus(httpClient, txid, argv.network) : undefined,
prevOutputs: argv.fetchInputs ? await fetchPrevOutputs(httpClient, tx) : undefined,
prevOutputSpends: argv.fetchSpends ? await fetchPrevOutputSpends(httpClient, tx) : undefined,
outputSpends:
Expand All @@ -254,7 +242,7 @@ export const cmdParseAddress = {
describe: 'parse address',
builder(b: yargs.Argv<unknown>): yargs.Argv<ArgsParseAddress> {
return b
.option('network', { alias: 'n', type: 'string' })
.options(getNetworkOptions())
.option('format', { choices: ['tree', 'json'], default: 'tree' } as const)
.option('convert', { type: 'boolean', default: false })
.option('all', { type: 'boolean', default: false })
Expand All @@ -272,7 +260,7 @@ export const cmdParseScript = {
describe: 'parse script',
builder(b: yargs.Argv<unknown>): yargs.Argv<ArgsParseScript> {
return b
.option('network', { alias: 'n', type: 'string' })
.options(getNetworkOptions())
.option('format', { choices: ['tree', 'json'], default: 'tree' } as const)
.option('all', { type: 'boolean', default: false })
.positional('script', { type: 'string', demandOption: true });
Expand All @@ -289,7 +277,7 @@ export const cmdGenerateAddress = {
describe: 'generate addresses',
builder(b: yargs.Argv<unknown>): yargs.Argv<ArgsGenerateAddress> {
return b
.option('network', { alias: 'n', type: 'string' })
.options(getNetworkOptionsDemand('bitcoin'))
.options(keyOptions)
.option('format', {
type: 'string',
Expand Down Expand Up @@ -321,7 +309,6 @@ export const cmdGenerateAddress = {
for (const address of generateAddress({
...argv,
index: indexRange,
network: getNetworkForName(argv.network ?? 'bitcoin'),
})) {
if (argv.format === 'tree') {
console.log(formatAddressTree(address));
Expand Down

0 comments on commit d5b73ca

Please sign in to comment.