@trezor/utxo-lib
Advanced tools
Comparing version 1.0.12 to 2.0.1
@@ -0,1 +1,35 @@ | ||
# 2.0.1 | ||
BREAKING CHANGES in `composeTx` module. | ||
renamed `composeTx` request parameters and response. | ||
- chore(repo): Upgrade TS 5.3 (#10017) (7277f9d0f) | ||
- chore(repo): upgrade to TS 5.2 (#9989) (bf8d0fe80) | ||
- chore(tests): cleanup jets configs (#9869) (7b68bab05) | ||
- feat(deps): update deps without breaking changes (7e0584c51) | ||
- chore: update prettier to v3 and reformat (4229fd483) | ||
- chore(desktop): update deps related to desktop packages (af412cfb5) | ||
- chore(utxo-lib): export all ComposeResult types (993dbf628) | ||
- chore(utxo-lib): version 2.0.0 (4d3495358) | ||
- refactor(utxo-lib): `composeTx` nonfinal result with inputs (6107d8d82) | ||
- refactor(utxo-lib): `composeTx` final result without nested transaction object (bb379b47d) | ||
- chore(utxo-lib): `composeTx` remove `basePath` and `changeId` params (8a6dacfc6) | ||
- refactor(utxo-lib): `composeTx` make changeAddress param generic (9f91c0911) | ||
- refactor(utxo-lib): `composeTx` make ComposeOutput and ComposedTransaction.output generic (2e4b3563a) | ||
- chore(utxo-lib): `composeTx` simplify processing result from `coinselect` (af7ca4837) | ||
- refactor(utxo-lib): `composeTx` strongly typed errors (3d8ce504a) | ||
- chore(utxo-lib): `composeUtils` simplify outputs sorting (e78afec83) | ||
- chore(utxo-lib): `composeUtils` remove unnecessary function (a6d54e443) | ||
- refactor(utxo-lib): `composeUtils` use payments module to create `script` used in `CoinSelectOutput` (2180ea28a) | ||
- refactor(utxo-lib): `coinselect` add changeOutput to CoinSelectOptions (1ba5f0aad) | ||
- refactor(utxo-lib): `composeTx` replace Permutation class with simple function (a1ccae45f) | ||
- refactor(utxo-lib): `composeTx` ComposedTxOutput rename `opReturnData` to `dataHex` (6c36de145) | ||
- refactor(utxo-lib): `composeTx` ComposeOutput rename `type` field (d3c6c82e0) | ||
- refactor(utxo-lib): `composeTx` make ComposeInput and ComposedTransaction.input generic (3e3d2a601) | ||
- refactor(utxo-lib): `composeTx` ComposeInput and ComposedTxInput rename `transactionHash` and `hash` to `txid` (939c153ff) | ||
- refactor(utxo-lib): `composeTx` ComposeInput and ComposedTxInput rename `index` to `vout` (f0a434698) | ||
- refactor(utxo-lib): `composeTx` ComposeInput and ComposedTxOutput rename `value` to `amount` (22414faaa) | ||
- refactor(utxo-lib): `composeTx` ComposeInput: rename `height` to `confirmations` (070f3d06f) | ||
- chore(utxo-lib): `composeTx` ComposeInput: remove `addressPath`, `tsize` and `vsize` fields (4e1d79151) | ||
# 1.0.11 | ||
@@ -2,0 +36,0 @@ |
@@ -182,5 +182,7 @@ "use strict"; | ||
function finalize(inputs, outputs, feeRate, options) { | ||
const blankOutput = { script: { length: exports.OUTPUT_SCRIPT_LENGTH[options.txType] } }; | ||
const changeOutput = options.changeOutput || { | ||
script: { length: exports.OUTPUT_SCRIPT_LENGTH[options.txType] }, | ||
}; | ||
const fee = getFee(inputs, outputs, feeRate, options); | ||
const feeAfterExtraOutput = getFee(inputs, [...outputs, blankOutput], feeRate, options); | ||
const feeAfterExtraOutput = getFee(inputs, [...outputs, changeOutput], feeRate, options); | ||
const sumInputs = sumOrNaN(inputs); | ||
@@ -197,8 +199,3 @@ const sumOutputs = sumOrNaN(outputs); | ||
if (remainderAfterExtraOutput.gte(new BN(dustAmount))) { | ||
finalOutputs.push({ | ||
value: remainderAfterExtraOutput.toString(), | ||
script: { | ||
length: exports.OUTPUT_SCRIPT_LENGTH[options.txType], | ||
}, | ||
}); | ||
finalOutputs.push(Object.assign(Object.assign({}, changeOutput), { value: remainderAfterExtraOutput.toString() })); | ||
} | ||
@@ -205,0 +202,0 @@ return { |
@@ -1,4 +0,4 @@ | ||
import { ComposeInput, ComposeOutput, CoinSelectPaymentType, CoinSelectSuccess, CoinSelectFailure } from '../types'; | ||
import { ComposeInput, ComposeOutput, ComposeChangeAddress, CoinSelectPaymentType, CoinSelectSuccess, CoinSelectFailure } from '../types'; | ||
import type { Network } from '../networks'; | ||
export declare function coinselect(txType: CoinSelectPaymentType, utxos: ComposeInput[], rOutputs: ComposeOutput[], height: number, feeRate: number, longTermFeeRate: number | undefined, countMax: boolean, countMaxId: number, dustThreshold: number, network: Network, baseFee?: number, floorBaseFee?: boolean, skipPermutation?: boolean): CoinSelectSuccess | CoinSelectFailure; | ||
export declare function coinselect(txType: CoinSelectPaymentType, utxos: ComposeInput[], rOutputs: ComposeOutput[], changeAddress: ComposeChangeAddress, feeRate: number, longTermFeeRate: number | undefined, countMax: boolean, countMaxId: number, dustThreshold: number, network: Network, baseFee?: number, floorBaseFee?: boolean, skipPermutation?: boolean): CoinSelectSuccess | CoinSelectFailure; | ||
//# sourceMappingURL=coinselect.d.ts.map |
@@ -9,8 +9,10 @@ "use strict"; | ||
const composeUtils_1 = require("./composeUtils"); | ||
function coinselect(txType, utxos, rOutputs, height, feeRate, longTermFeeRate, countMax, countMaxId, dustThreshold, network, baseFee, floorBaseFee, skipPermutation) { | ||
const inputs0 = (0, composeUtils_1.convertInputs)(utxos, height, txType); | ||
function coinselect(txType, utxos, rOutputs, changeAddress, feeRate, longTermFeeRate, countMax, countMaxId, dustThreshold, network, baseFee, floorBaseFee, skipPermutation) { | ||
const inputs0 = (0, composeUtils_1.convertInputs)(utxos, txType); | ||
const outputs0 = (0, composeUtils_1.convertOutputs)(rOutputs, network, txType); | ||
const feePolicy = (0, coinselectUtils_1.getFeePolicy)(network); | ||
const [changeOutput] = (0, composeUtils_1.convertOutputs)([Object.assign({ type: 'send-max' }, changeAddress)], network, txType); | ||
const options = { | ||
txType, | ||
changeOutput, | ||
dustThreshold, | ||
@@ -17,0 +19,0 @@ longTermFeeRate, |
import { CoinSelectPaymentType, CoinSelectInput, CoinSelectOutput, ComposeInput, ComposeOutput } from '../types'; | ||
import type { Network } from '../networks'; | ||
export declare function convertInputs(inputs: ComposeInput[], height: number | undefined, txType: CoinSelectPaymentType): CoinSelectInput[]; | ||
export declare function getScriptFromAddress(address: string, network: Network): { | ||
length: number; | ||
}; | ||
export declare function convertInputs(inputs: ComposeInput[], txType: CoinSelectPaymentType): CoinSelectInput[]; | ||
export declare function convertOutputs(outputs: ComposeOutput[], network: Network, txType: CoinSelectPaymentType): CoinSelectOutput[]; | ||
export declare function convertFeeRate(rate: string | number): number | undefined; | ||
//# sourceMappingURL=composeUtils.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.convertFeeRate = exports.convertOutputs = exports.getScriptFromAddress = exports.convertInputs = void 0; | ||
exports.convertFeeRate = exports.convertOutputs = exports.convertInputs = void 0; | ||
const BitcoinJsAddress = require("../address"); | ||
const embed_1 = require("../payments/embed"); | ||
const coinselectUtils_1 = require("../coinselect/coinselectUtils"); | ||
function convertInputs(inputs, height = 0, txType) { | ||
function convertInputs(inputs, txType) { | ||
return inputs | ||
@@ -12,6 +13,6 @@ .map((input, i) => ({ | ||
script: { length: coinselectUtils_1.INPUT_SCRIPT_LENGTH[txType] }, | ||
value: input.value, | ||
value: input.amount, | ||
own: input.own, | ||
coinbase: input.coinbase, | ||
confirmations: input.height == null ? 0 : 1 + height - input.height, | ||
confirmations: input.confirmations, | ||
required: input.required, | ||
@@ -22,8 +23,2 @@ })) | ||
exports.convertInputs = convertInputs; | ||
function getScriptFromAddress(address, network) { | ||
return { | ||
length: BitcoinJsAddress.toOutputScript(address, network).length, | ||
}; | ||
} | ||
exports.getScriptFromAddress = getScriptFromAddress; | ||
function convertOutputs(outputs, network, txType) { | ||
@@ -33,9 +28,9 @@ const script = { length: coinselectUtils_1.OUTPUT_SCRIPT_LENGTH[txType] }; | ||
.map(output => { | ||
if (output.type === 'complete') { | ||
if (output.type === 'payment') { | ||
return { | ||
value: output.amount, | ||
script: getScriptFromAddress(output.address, network), | ||
script: BitcoinJsAddress.toOutputScript(output.address, network), | ||
}; | ||
} | ||
if (output.type === 'noaddress') { | ||
if (output.type === 'payment-noaddress') { | ||
return { | ||
@@ -49,3 +44,3 @@ value: output.amount, | ||
value: '0', | ||
script: { length: 2 + output.dataHex.length / 2 }, | ||
script: (0, embed_1.p2data)({ data: [Buffer.from(output.dataHex, 'hex')] }).output, | ||
}; | ||
@@ -55,3 +50,3 @@ } | ||
return { | ||
script: getScriptFromAddress(output.address, network), | ||
script: BitcoinJsAddress.toOutputScript(output.address, network), | ||
}; | ||
@@ -64,3 +59,3 @@ } | ||
} | ||
throw new Error('WRONG-OUTPUT-TYPE'); | ||
throw new Error('INCORRECT-OUTPUT-TYPE'); | ||
}) | ||
@@ -67,0 +62,0 @@ .map(output => Object.assign(output, { weight: (0, coinselectUtils_1.outputWeight)(output) })); |
@@ -1,3 +0,3 @@ | ||
import { ComposeRequest, ComposeResult } from '../types'; | ||
export declare function composeTx({ txType, utxos, outputs, height, feeRate, longTermFeeRate, basePath, network, changeId, changeAddress, dustThreshold, baseFee, floorBaseFee, skipPermutation, }: ComposeRequest): ComposeResult; | ||
import { ComposeRequest, ComposeInput, ComposeOutput, ComposeChangeAddress, ComposeResult } from '../types'; | ||
export declare function composeTx<Input extends ComposeInput, Output extends ComposeOutput, Change extends ComposeChangeAddress>(request: ComposeRequest<Input, Output, Change>): ComposeResult<Input, Output, Change>; | ||
//# sourceMappingURL=index.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.composeTx = void 0; | ||
const request = require("./request"); | ||
const result = require("./result"); | ||
const transaction = require("./transaction"); | ||
const request_1 = require("./request"); | ||
const result_1 = require("./result"); | ||
const composeUtils_1 = require("./composeUtils"); | ||
const coinselect_1 = require("./coinselect"); | ||
function composeTx({ txType, utxos, outputs, height, feeRate, longTermFeeRate, basePath, network, changeId, changeAddress, dustThreshold, baseFee, floorBaseFee, skipPermutation, }) { | ||
function composeTx(request) { | ||
const { utxos, outputs, feeRate, longTermFeeRate } = request; | ||
if (outputs.length === 0) { | ||
return result.empty; | ||
return { type: 'error', error: 'MISSING-OUTPUTS' }; | ||
} | ||
if (utxos.length === 0) { | ||
return { type: 'error', error: 'NOT-ENOUGH-FUNDS' }; | ||
return { type: 'error', error: 'MISSING-UTXOS' }; | ||
} | ||
@@ -29,31 +29,20 @@ const feeRateNumber = (0, composeUtils_1.convertFeeRate)(feeRate); | ||
try { | ||
countMax = request.getMax(outputs); | ||
countMax = (0, request_1.getMax)(outputs); | ||
} | ||
catch (e) { | ||
if (e instanceof Error) { | ||
return { type: 'error', error: e.message }; | ||
} | ||
return { type: 'error', error: `${e}` }; | ||
catch (error) { | ||
return (0, result_1.getErrorResult)(error); | ||
} | ||
const splitOutputs = request.splitByCompleteness(outputs); | ||
let csResult = { success: false }; | ||
let result = { success: false }; | ||
try { | ||
csResult = (0, coinselect_1.coinselect)(txType || 'p2pkh', utxos, outputs, height, feeRateNumber, longTermFeeRateNumber, countMax.exists, countMax.id, dustThreshold, network, baseFee, floorBaseFee, skipPermutation); | ||
result = (0, coinselect_1.coinselect)(request.txType || 'p2pkh', utxos, outputs, request.changeAddress, feeRateNumber, longTermFeeRateNumber, countMax.exists, countMax.id, request.dustThreshold, request.network, request.baseFee, request.floorBaseFee, request.skipPermutation); | ||
} | ||
catch (e) { | ||
if (e instanceof Error) { | ||
return { type: 'error', error: e.message }; | ||
} | ||
return { type: 'error', error: `${e}` }; | ||
catch (error) { | ||
return (0, result_1.getErrorResult)(error); | ||
} | ||
if (!csResult.success) { | ||
if (!result.success) { | ||
return { type: 'error', error: 'NOT-ENOUGH-FUNDS' }; | ||
} | ||
if (splitOutputs.incomplete.length > 0) { | ||
return result.getNonfinalResult(csResult); | ||
} | ||
const resTransaction = transaction.createTransaction(utxos, csResult.payload.inputs, splitOutputs.complete, csResult.payload.outputs, basePath, changeId, changeAddress, network, skipPermutation); | ||
return result.getFinalResult(csResult, resTransaction); | ||
return (0, result_1.getResult)(request, result); | ||
} | ||
exports.composeTx = composeTx; | ||
//# sourceMappingURL=index.js.map |
@@ -1,6 +0,2 @@ | ||
import { ComposeOutput, ComposeFinalOutput, ComposeNotFinalOutput } from '../types'; | ||
export declare function splitByCompleteness(outputs: ComposeOutput[]): { | ||
complete: ComposeFinalOutput[]; | ||
incomplete: ComposeNotFinalOutput[]; | ||
}; | ||
import { ComposeOutput } from '../types'; | ||
export declare function getMax(outputs: ComposeOutput[]): { | ||
@@ -7,0 +3,0 @@ id: number; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getMax = exports.splitByCompleteness = void 0; | ||
function splitByCompleteness(outputs) { | ||
const complete = []; | ||
const incomplete = []; | ||
outputs.forEach(output => { | ||
if (output.type === 'complete' || | ||
output.type === 'send-max' || | ||
output.type === 'opreturn') { | ||
complete.push(output); | ||
} | ||
else { | ||
incomplete.push(output); | ||
} | ||
}); | ||
return { | ||
complete, | ||
incomplete, | ||
}; | ||
} | ||
exports.splitByCompleteness = splitByCompleteness; | ||
exports.getMax = void 0; | ||
function getMax(outputs) { | ||
@@ -24,0 +5,0 @@ const countMaxRequests = outputs.filter(output => output.type === 'send-max-noaddress' || output.type === 'send-max'); |
@@ -1,5 +0,4 @@ | ||
import { CoinSelectSuccess, ComposedTransaction, ComposeResult } from '../types'; | ||
export declare const empty: ComposeResult; | ||
export declare function getNonfinalResult(result: CoinSelectSuccess): ComposeResult; | ||
export declare function getFinalResult(result: CoinSelectSuccess, transaction: ComposedTransaction): ComposeResult; | ||
import { CoinSelectSuccess, ComposeRequest, ComposeInput, ComposeOutput, ComposeChangeAddress, ComposeResultError, ComposeResultNonFinal, ComposeResultFinal } from '../types'; | ||
export declare function getErrorResult(error: unknown): ComposeResultError; | ||
export declare function getResult<Input extends ComposeInput, Output extends ComposeOutput, Change extends ComposeChangeAddress>(request: ComposeRequest<Input, Output, Change>, result: CoinSelectSuccess): ComposeResultNonFinal<Input> | ComposeResultFinal<Input, Output, Change>; | ||
//# sourceMappingURL=result.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getFinalResult = exports.getNonfinalResult = exports.empty = void 0; | ||
exports.empty = { | ||
type: 'error', | ||
error: 'EMPTY', | ||
}; | ||
function getNonfinalResult(result) { | ||
exports.getResult = exports.getErrorResult = void 0; | ||
const transaction_1 = require("./transaction"); | ||
const types_1 = require("../types"); | ||
function getErrorResult(error) { | ||
const message = error instanceof Error ? error.message : `${error}`; | ||
const known = types_1.COMPOSE_ERROR_TYPES.find(e => e === message); | ||
if (known) { | ||
return { type: 'error', error: known }; | ||
} | ||
return { type: 'error', error: 'COINSELECT', message }; | ||
} | ||
exports.getErrorResult = getErrorResult; | ||
function getNonfinalResult(utxos, result) { | ||
const { max, fee, feePerByte, bytes, totalSpent } = result.payload; | ||
const inputs = result.payload.inputs.map(input => utxos[input.i]); | ||
return { | ||
@@ -17,18 +25,36 @@ type: 'nonfinal', | ||
totalSpent, | ||
inputs, | ||
}; | ||
} | ||
exports.getNonfinalResult = getNonfinalResult; | ||
function getFinalResult(result, transaction) { | ||
const { max, fee, feePerByte, bytes, totalSpent } = result.payload; | ||
return Object.assign({ type: 'final', fee: fee.toString(), feePerByte: feePerByte.toString(), bytes, | ||
max, | ||
totalSpent }, transaction); | ||
} | ||
function splitByCompleteness(outputs) { | ||
const complete = []; | ||
const incomplete = []; | ||
outputs.forEach(output => { | ||
if (output.type === 'payment' || output.type === 'send-max' || output.type === 'opreturn') { | ||
complete.push(output); | ||
} | ||
else { | ||
incomplete.push(output); | ||
} | ||
}); | ||
return { | ||
type: 'final', | ||
fee: fee.toString(), | ||
feePerByte: feePerByte.toString(), | ||
bytes, | ||
transaction, | ||
max, | ||
totalSpent, | ||
complete, | ||
incomplete, | ||
}; | ||
} | ||
exports.getFinalResult = getFinalResult; | ||
function getResult(request, result) { | ||
const splitOutputs = splitByCompleteness(request.outputs); | ||
if (splitOutputs.incomplete.length > 0) { | ||
return getNonfinalResult(request.utxos, result); | ||
} | ||
const transaction = (0, transaction_1.createTransaction)(request.utxos, result.payload.inputs, splitOutputs.complete, result.payload.outputs, request.changeAddress, request.skipPermutation); | ||
return getFinalResult(result, transaction); | ||
} | ||
exports.getResult = getResult; | ||
//# sourceMappingURL=result.js.map |
@@ -1,4 +0,3 @@ | ||
import { ComposeInput, ComposeFinalOutput, ComposedTransaction, CoinSelectInput, CoinSelectOutputFinal } from '../types'; | ||
import type { Network } from '../networks'; | ||
export declare function createTransaction(allInputs: ComposeInput[], selectedInputs: CoinSelectInput[], allOutputs: ComposeFinalOutput[], selectedOutputs: CoinSelectOutputFinal[], basePath: number[], changeId: number, changeAddress: string, network: Network, skipPermutation?: boolean): ComposedTransaction; | ||
import { ComposeInput, ComposeChangeAddress, ComposeFinalOutput, ComposedTransaction, CoinSelectInput, CoinSelectOutputFinal } from '../types'; | ||
export declare function createTransaction<Input extends ComposeInput, Change extends ComposeChangeAddress>(allInputs: Input[], selectedInputs: CoinSelectInput[], allOutputs: ComposeFinalOutput[], selectedOutputs: CoinSelectOutputFinal[], changeAddress: Change, skipPermutation?: boolean): ComposedTransaction<Input, ComposeFinalOutput, Change>; | ||
//# sourceMappingURL=transaction.d.ts.map |
@@ -5,74 +5,37 @@ "use strict"; | ||
const BN = require("bn.js"); | ||
const BitcoinJsAddress = require("../address"); | ||
const embed_1 = require("../payments/embed"); | ||
const permutation_1 = require("./permutation"); | ||
const bufferutils_1 = require("../bufferutils"); | ||
function convertInput(utxo, basePath) { | ||
return { | ||
hash: (0, bufferutils_1.reverseBuffer)(Buffer.from(utxo.transactionHash, 'hex')), | ||
index: utxo.index, | ||
path: basePath.concat([...utxo.addressPath]), | ||
amount: utxo.value, | ||
}; | ||
function convertOutput(selectedOutput, composeOutput) { | ||
if (composeOutput.type === 'change') { | ||
return Object.assign(Object.assign({}, composeOutput), { amount: selectedOutput.value }); | ||
} | ||
if (composeOutput.type === 'opreturn') { | ||
return composeOutput; | ||
} | ||
return Object.assign(Object.assign({}, composeOutput), { type: 'payment', amount: selectedOutput.value }); | ||
} | ||
function convertOpReturnOutput(opReturnData) { | ||
const opReturnDataBuffer = Buffer.from(opReturnData, 'hex'); | ||
const output = { | ||
opReturnData: opReturnDataBuffer, | ||
value: undefined, | ||
}; | ||
const script = (0, embed_1.p2data)({ data: [opReturnDataBuffer] }).output; | ||
return { | ||
output, | ||
script, | ||
}; | ||
function inputComparator(a, b) { | ||
return Buffer.from(a.txid, 'hex').compare(Buffer.from(b.txid, 'hex')) || a.vout - b.vout; | ||
} | ||
function convertOutput(address, value, network, basePath, changeId, isChange) { | ||
const output = isChange | ||
? { | ||
path: [...basePath, 1, changeId], | ||
value, | ||
} | ||
: { | ||
address, | ||
value, | ||
}; | ||
return { | ||
output, | ||
script: BitcoinJsAddress.toOutputScript(address, network), | ||
}; | ||
function outputComparator(a, b) { | ||
return (new BN(a.value).cmp(new BN(b.value)) || | ||
(Buffer.isBuffer(a.script) && Buffer.isBuffer(b.script) | ||
? a.script.compare(b.script) | ||
: a.script.length - b.script.length)); | ||
} | ||
function inputComparator(aHash, aVout, bHash, bVout) { | ||
return (0, bufferutils_1.reverseBuffer)(aHash).compare((0, bufferutils_1.reverseBuffer)(bHash)) || aVout - bVout; | ||
} | ||
function outputComparator(aScript, aValue, bScript, bValue) { | ||
return new BN(aValue).cmp(new BN(bValue)) || aScript.compare(bScript); | ||
} | ||
function createTransaction(allInputs, selectedInputs, allOutputs, selectedOutputs, basePath, changeId, changeAddress, network, skipPermutation) { | ||
const convertedInputs = selectedInputs.map(input => convertInput(allInputs[input.i], basePath)); | ||
const convertedOutputs = selectedOutputs.map((output, i) => { | ||
const isChange = i === allOutputs.length; | ||
const original = allOutputs[i]; | ||
if (original && original.type === 'opreturn') { | ||
return convertOpReturnOutput(original.dataHex); | ||
} | ||
const address = !original ? changeAddress : original.address; | ||
const amount = output.value; | ||
return convertOutput(address, amount, network, basePath, changeId, isChange); | ||
}); | ||
function createTransaction(allInputs, selectedInputs, allOutputs, selectedOutputs, changeAddress, skipPermutation) { | ||
const convertedInputs = selectedInputs.map(input => allInputs[input.i]); | ||
const convertedOutputs = selectedOutputs.map((output, index) => convertOutput(output, allOutputs[index] || Object.assign({ type: 'change' }, changeAddress))); | ||
const defaultPermutation = convertedOutputs.map((_, index) => index); | ||
if (skipPermutation) { | ||
return { | ||
inputs: convertedInputs, | ||
outputs: new permutation_1.Permutation(convertedOutputs.map(o => o.output), convertedOutputs.map((_o, i) => i)), | ||
outputs: convertedOutputs, | ||
outputsPermutation: defaultPermutation, | ||
}; | ||
} | ||
convertedInputs.sort((a, b) => inputComparator(a.hash, a.index, b.hash, b.index)); | ||
const permutedOutputs = permutation_1.Permutation.fromFunction(convertedOutputs, (a, b) => { | ||
const aValue = typeof a.output.value === 'string' ? a.output.value : '0'; | ||
const bValue = typeof b.output.value === 'string' ? b.output.value : '0'; | ||
return outputComparator(a.script, aValue, b.script, bValue); | ||
}).map(o => o.output); | ||
const permutation = defaultPermutation.sort((a, b) => outputComparator(selectedOutputs[a], selectedOutputs[b])); | ||
const sortedOutputs = permutation.map(index => convertedOutputs[index]); | ||
return { | ||
inputs: convertedInputs, | ||
outputs: permutedOutputs, | ||
inputs: convertedInputs.sort(inputComparator), | ||
outputs: sortedOutputs, | ||
outputsPermutation: permutation, | ||
}; | ||
@@ -79,0 +42,0 @@ } |
@@ -14,5 +14,5 @@ import * as address from './address'; | ||
export type { PaymentType } from './derivation'; | ||
export type { ComposeInput, ComposeOutput, ComposeRequest, ComposeResult, ComposeResultFinal, ComposedTxInput, ComposedTxOutput, ComposedTransaction, CoinSelectPaymentType, } from './types'; | ||
export type { ComposeInput, ComposeOutput, ComposeChangeAddress, ComposeRequest, ComposeResult, ComposeResultNonFinal, ComposeResultError, ComposeResultFinal, ComposedTransaction, CoinSelectPaymentType, } from './types'; | ||
export type { Network } from './networks'; | ||
export type { BIP32Interface } from './bip32'; | ||
//# sourceMappingURL=index.d.ts.map |
export type CoinSelectPaymentType = 'p2pkh' | 'p2sh' | 'p2tr' | 'p2wpkh' | 'p2wsh'; | ||
export interface CoinSelectOptions { | ||
txType: CoinSelectPaymentType; | ||
changeOutput?: CoinSelectOutput; | ||
dustThreshold?: number; | ||
@@ -5,0 +6,0 @@ longTermFeeRate?: number; |
@@ -1,46 +0,54 @@ | ||
/// <reference types="node" /> | ||
import type { Network } from '../networks'; | ||
import type { CoinSelectPaymentType } from './coinselect'; | ||
export interface ComposeInput { | ||
index: number; | ||
transactionHash: string; | ||
value: string; | ||
addressPath: [number, number]; | ||
height?: number; | ||
vout: number; | ||
txid: string; | ||
amount: string; | ||
coinbase: boolean; | ||
tsize: number; | ||
vsize: number; | ||
own: boolean; | ||
confirmations: number; | ||
required?: boolean; | ||
confirmations?: number; | ||
} | ||
export type ComposeFinalOutput = { | ||
type: 'complete'; | ||
export interface ComposeOutputPayment { | ||
type: 'payment'; | ||
address: string; | ||
amount: string; | ||
} | { | ||
} | ||
export interface ComposeOutputPaymentNoAddress { | ||
type: 'payment-noaddress'; | ||
amount: string; | ||
} | ||
export interface ComposeOutputSendMax { | ||
type: 'send-max'; | ||
address: string; | ||
} | { | ||
amount?: typeof undefined; | ||
} | ||
export interface ComposeOutputSendMaxNoAddress { | ||
type: 'send-max-noaddress'; | ||
amount?: typeof undefined; | ||
} | ||
export interface ComposeOutputOpreturn { | ||
type: 'opreturn'; | ||
dataHex: string; | ||
}; | ||
export type ComposeNotFinalOutput = { | ||
type: 'send-max-noaddress'; | ||
} | { | ||
type: 'noaddress'; | ||
amount?: typeof undefined; | ||
address?: typeof undefined; | ||
} | ||
export interface ComposeOutputChange { | ||
type: 'change'; | ||
amount: string; | ||
}; | ||
} | ||
export type ComposeFinalOutput = ComposeOutputPayment | ComposeOutputSendMax | ComposeOutputOpreturn; | ||
export type ComposeNotFinalOutput = ComposeOutputPaymentNoAddress | ComposeOutputSendMaxNoAddress; | ||
export type ComposeOutput = ComposeFinalOutput | ComposeNotFinalOutput; | ||
export interface ComposeRequest { | ||
export interface ComposeChangeAddress { | ||
address: string; | ||
} | ||
export interface ComposeRequest<Input extends ComposeInput, Output extends ComposeOutput, Change extends ComposeChangeAddress> { | ||
txType?: CoinSelectPaymentType; | ||
utxos: ComposeInput[]; | ||
outputs: ComposeOutput[]; | ||
height: number; | ||
utxos: Input[]; | ||
outputs: Output[]; | ||
feeRate: string | number; | ||
longTermFeeRate?: string | number; | ||
basePath: number[]; | ||
network: Network; | ||
changeId: number; | ||
changeAddress: string; | ||
changeAddress: Change; | ||
dustThreshold: number; | ||
@@ -52,36 +60,18 @@ baseFee?: number; | ||
} | ||
export type ComposedTxOutput = { | ||
path: number[]; | ||
value: string; | ||
address?: typeof undefined; | ||
opReturnData?: typeof undefined; | ||
type ComposedTransactionOutputs<T> = T extends ComposeOutputSendMax ? Omit<T, 'type'> & ComposeOutputPayment : T extends ComposeFinalOutput ? T : never; | ||
export interface ComposedTransaction<Input extends ComposeInput, Output extends ComposeOutput, Change extends ComposeChangeAddress> { | ||
inputs: Input[]; | ||
outputs: (ComposedTransactionOutputs<Output> | (Change & ComposeOutputChange))[]; | ||
outputsPermutation: number[]; | ||
} | ||
export declare const COMPOSE_ERROR_TYPES: readonly ["MISSING-UTXOS", "MISSING-OUTPUTS", "INCORRECT-OUTPUT-TYPE", "INCORRECT-FEE-RATE", "TWO-SEND-MAX", "NOT-ENOUGH-FUNDS"]; | ||
export type ComposeResultError = { | ||
type: 'error'; | ||
error: (typeof COMPOSE_ERROR_TYPES)[number]; | ||
} | { | ||
address: string; | ||
value: string; | ||
path?: typeof undefined; | ||
opReturnData?: typeof undefined; | ||
} | { | ||
opReturnData: Buffer; | ||
path?: typeof undefined; | ||
address?: typeof undefined; | ||
value?: typeof undefined; | ||
type: 'error'; | ||
error: 'COINSELECT'; | ||
message: string; | ||
}; | ||
export interface ComposedTxInput { | ||
hash: Buffer; | ||
index: number; | ||
path: number[]; | ||
amount: string; | ||
} | ||
export interface ComposedTransaction { | ||
inputs: ComposedTxInput[]; | ||
outputs: { | ||
sorted: ComposedTxOutput[]; | ||
permutation: number[]; | ||
}; | ||
} | ||
export interface ComposeResultError { | ||
type: 'error'; | ||
error: string; | ||
} | ||
export interface ComposeResultNonFinal { | ||
export interface ComposeResultNonFinal<Input extends ComposeInput> { | ||
type: 'nonfinal'; | ||
@@ -93,4 +83,5 @@ max?: string; | ||
bytes: number; | ||
inputs: Input[]; | ||
} | ||
export interface ComposeResultFinal { | ||
export interface ComposeResultFinal<Input extends ComposeInput, Output extends ComposeOutput, Change extends ComposeChangeAddress> extends ComposedTransaction<Input, Output, Change> { | ||
type: 'final'; | ||
@@ -102,5 +93,8 @@ max?: string; | ||
bytes: number; | ||
transaction: ComposedTransaction; | ||
inputs: Input[]; | ||
outputs: (ComposedTransactionOutputs<Output> | (Change & ComposeOutputChange))[]; | ||
outputsPermutation: number[]; | ||
} | ||
export type ComposeResult = ComposeResultError | ComposeResultNonFinal | ComposeResultFinal; | ||
export type ComposeResult<Input extends ComposeInput, Output extends ComposeOutput, Change extends ComposeChangeAddress> = ComposeResultError | ComposeResultNonFinal<Input> | ComposeResultFinal<Input, Output, Change>; | ||
export {}; | ||
//# sourceMappingURL=compose.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.COMPOSE_ERROR_TYPES = void 0; | ||
exports.COMPOSE_ERROR_TYPES = [ | ||
'MISSING-UTXOS', | ||
'MISSING-OUTPUTS', | ||
'INCORRECT-OUTPUT-TYPE', | ||
'INCORRECT-FEE-RATE', | ||
'TWO-SEND-MAX', | ||
'NOT-ENOUGH-FUNDS', | ||
]; | ||
//# sourceMappingURL=compose.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getTransactionVbytes = exports.getTransactionVbytesFromAddresses = void 0; | ||
const BitcoinJsAddress = require("./address"); | ||
const coinselectUtils_1 = require("./coinselect/coinselectUtils"); | ||
const composeUtils_1 = require("./compose/composeUtils"); | ||
const address_1 = require("./address"); | ||
@@ -22,3 +22,3 @@ const isKnownInputAddress = (type) => type in coinselectUtils_1.INPUT_SCRIPT_LENGTH; | ||
try { | ||
length = (0, composeUtils_1.getScriptFromAddress)(address, network).length; | ||
length = BitcoinJsAddress.toOutputScript(address, network).length; | ||
} | ||
@@ -25,0 +25,0 @@ catch (_b) { |
{ | ||
"name": "@trezor/utxo-lib", | ||
"version": "1.0.12", | ||
"version": "2.0.1", | ||
"author": "Trezor <info@trezor.io>", | ||
@@ -39,3 +39,3 @@ "homepage": "https://github.com/trezor/trezor-suite/tree/develop/packages/utxo-lib", | ||
"dependencies": { | ||
"@trezor/utils": "9.0.14", | ||
"@trezor/utils": "9.0.15", | ||
"bchaddrjs": "^0.5.2", | ||
@@ -57,17 +57,17 @@ "bech32": "^2.0.0", | ||
"varuint-bitcoin": "^1.1.2", | ||
"wif": "^2.0.6" | ||
"wif": "^4.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/bchaddrjs": "^0.4.0", | ||
"@types/bs58": "^4.0.1", | ||
"@types/bs58check": "^2.1.0", | ||
"@types/create-hash": "^1.2.2", | ||
"@types/create-hmac": "^1.1.0", | ||
"@types/wif": "^2.0.2", | ||
"@types/bchaddrjs": "^0.4.2", | ||
"@types/bs58": "^4.0.3", | ||
"@types/bs58check": "^2.1.1", | ||
"@types/create-hash": "^1.2.4", | ||
"@types/create-hmac": "^1.1.2", | ||
"@types/wif": "^2.0.4", | ||
"jest": "^26.6.3", | ||
"minimaldata": "^1.0.2", | ||
"rimraf": "^5.0.1", | ||
"tsx": "^3.12.7", | ||
"typescript": "4.9.5" | ||
"rimraf": "^5.0.5", | ||
"tsx": "^3.14.0", | ||
"typescript": "5.3.2" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
224471
108
5550
+ Added@trezor/utils@9.0.15(transitive)
+ Addedwif@4.0.0(transitive)
- Removed@trezor/utils@9.0.14(transitive)
- Removedwif@2.0.6(transitive)
Updated@trezor/utils@9.0.15
Updatedwif@^4.0.0