PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo-forks/avalanchejs/src/vms/avm
Просмотр файла: builder.ts
import {
BaseTx as AvaxBaseTx,
TransferableInput,
TransferableOutput,
} from '../../serializable/avax';
import type { Utxo } from '../../serializable/avax/utxo';
import { ExportTx, ImportTx } from '../../serializable/avm';
import { Id } from '../../serializable/fxs/common';
import { addressesFromBytes } from '../../utils';
import { AddressMaps } from '../../utils/addressMap';
import { getImportedInputsFromUtxos } from '../../utils/builderUtils';
import { compareTransferableOutputs } from '../../utils/sort';
import { transferableAmounts } from '../../utils/transferableAmounts';
import { defaultSpendOptions } from '../common/defaultSpendOptions';
import type { SpendOptions } from '../common/models';
import { UnsignedTx } from '../common/unsignedTx';
import type { Context } from '../context/model';
import { BaseTx } from '../../serializable/avm/baseTx';
import type { UTXOCalculationResult } from '../utils/calculateSpend';
import { calculateUTXOSpend } from '../utils/calculateSpend';
import { useAvmAndCorethUTXOs } from './utxoCalculationFns';
import { baseTxUnsafeAvm } from '../common';
/**
*
* @param sourceChainId id of the chain to import from
* @param utxos list of utxos
* @param toAddresses addresses to import the tx
* @param fromAddressesBytes used to filter UTXOs
* @param options used to filter UTXOs
* @param threshold number of signers to put on the resulting utxo
* @param locktime time the resulting utxo unlocks
* @returns
*/
export function newImportTx(
context: Context,
sourceChainId: string,
utxos: Utxo[],
toAddresses: Uint8Array[],
fromAddressesBytes: Uint8Array[],
options?: SpendOptions,
threshold = 1,
locktime = 0n,
) {
const fromAddresses = addressesFromBytes(fromAddressesBytes);
const defaultedOptions = defaultSpendOptions(fromAddressesBytes, options);
const { importedAmounts, importedInputs, inputUTXOs } =
getImportedInputsFromUtxos(
utxos,
fromAddressesBytes,
defaultedOptions.minIssuanceTime,
);
if (!importedInputs.length) {
throw new Error('no UTXOs available to import');
}
importedInputs.sort(TransferableInput.compare);
const addressMaps = AddressMaps.fromTransferableInputs(
importedInputs,
utxos,
defaultedOptions.minIssuanceTime,
fromAddressesBytes,
);
const importedAvax = importedAmounts[context.avaxAssetID] ?? 0n;
let inputOutputs: UTXOCalculationResult = {
inputs: [],
inputUTXOs: [],
stakeOutputs: [],
changeOutputs: [],
addressMaps: new AddressMaps(),
};
const txFee = context.baseTxFee;
const avaxAssetID = context.avaxAssetID;
if (importedAvax > txFee) {
importedAmounts[avaxAssetID] -= txFee;
} else {
if (importedAvax < txFee) {
const toBurn = new Map<string, bigint>([
[avaxAssetID, txFee - importedAvax],
]);
inputOutputs = calculateUTXOSpend(
toBurn,
undefined,
utxos,
fromAddresses,
defaultedOptions,
[useAvmAndCorethUTXOs],
);
}
delete importedAmounts[avaxAssetID];
}
inputUTXOs.push(...(inputOutputs.inputUTXOs || []));
addressMaps.merge(inputOutputs.addressMaps || new AddressMaps());
Object.entries(importedAmounts).forEach(([assetID, amount]) => {
inputOutputs.changeOutputs.push(
TransferableOutput.fromNative(
assetID,
amount,
toAddresses,
locktime,
threshold,
),
);
});
return new UnsignedTx(
new ImportTx(
AvaxBaseTx.fromNative(
context.networkID,
context.xBlockchainID,
inputOutputs.changeOutputs || [],
inputOutputs.inputs || [],
defaultedOptions.memo,
),
Id.fromString(sourceChainId),
importedInputs,
),
inputUTXOs,
addressMaps,
);
}
/**
* Format export Tx given a set of utxos. The priority is determined by the order of the utxo
* array. Fee is automatically added
* @param destinationChain - id of the destination chain
* @param fromAddresses - used for selecting which utxos are signable
* @param utxoSet - list of utxos to spend from
* @param outputs - the final desired output
* @param options - see SpendingOptions
*/
export function newExportTx(
context: Context,
destinationChain: string,
fromAddressesBytes: Uint8Array[],
utxoSet: Utxo[],
outputs: TransferableOutput[],
options?: SpendOptions,
) {
const fromAddresses = addressesFromBytes(fromAddressesBytes);
const defaultedOptions = defaultSpendOptions(fromAddressesBytes, options);
const toBurn = new Map<string, bigint>([
[context.avaxAssetID, context.baseTxFee],
]);
outputs.forEach((out) => {
const assetId = out.assetId.value();
toBurn.set(assetId, (toBurn.get(assetId) || 0n) + out.output.amount());
});
const { inputs, changeOutputs, inputUTXOs, addressMaps } = calculateUTXOSpend(
toBurn,
undefined,
utxoSet,
fromAddresses,
defaultedOptions,
[useAvmAndCorethUTXOs],
);
outputs.sort(compareTransferableOutputs);
return exportTxUnsafe(
context,
outputs,
changeOutputs,
inputs,
destinationChain,
defaultedOptions.memo,
inputUTXOs,
addressMaps,
);
}
/**
* Format base Tx given a set of utxos. The priority is determined by the order of the utxo
* array. Fee is automatically added
* @param fromAddresses - used for selecting which utxos are signable
* @param utxoSet - list of utxos to spend from
* @param outputs - the desired output (change outputs will be added to them automatically)
* @param options - see SpendingOptions
*/
export function newBaseTx(
context: Context,
fromAddressesBytes: Uint8Array[],
utxoSet: Utxo[],
outputs: TransferableOutput[],
options?: SpendOptions,
) {
const fromAddresses = addressesFromBytes(fromAddressesBytes);
const defaultedOptions = defaultSpendOptions(fromAddressesBytes, options);
const toBurn = new Map<string, bigint>([
[context.avaxAssetID, context.baseTxFee],
]);
outputs.forEach((out) => {
const assetId = out.assetId.value();
toBurn.set(assetId, (toBurn.get(assetId) || 0n) + out.output.amount());
});
const { inputs, inputUTXOs, changeOutputs, addressMaps } = calculateUTXOSpend(
toBurn,
undefined,
utxoSet,
fromAddresses,
defaultedOptions,
[useAvmAndCorethUTXOs],
);
const allOutputs = [...outputs, ...changeOutputs];
allOutputs.sort(compareTransferableOutputs);
return new UnsignedTx(
new BaseTx(
baseTxUnsafeAvm(context, allOutputs, inputs, defaultedOptions.memo),
),
inputUTXOs,
addressMaps,
);
}
/**
* Format export Tx based on inputs directly. extra inputs amounts are burned
* @param outputs - the total output for the tx
* @param changeOutputs - the output representing the remaining amounts from each input
* @param inputs - the inputs of the tx
* @param destinationChain - id of the destination chain
* @param memo - optional memo
*/
const exportTxUnsafe = (
context: Context,
outputs: TransferableOutput[],
changeOutputs: TransferableOutput[],
inputs: TransferableInput[],
destinationChain: string,
memo: Uint8Array,
inputUtxos: Utxo[],
sigMappings: AddressMaps,
) => {
outputs.sort(compareTransferableOutputs);
const outputAmts = transferableAmounts([...outputs, ...changeOutputs]);
const inputAmts = transferableAmounts(inputs);
// check outputs and change outputs are all covered by inputs given
// extra inputs are burned and is allowed
const allOutputsCovered = Object.entries(outputAmts).every(
([assetID, amount]) => inputAmts[assetID] && inputAmts[assetID] >= amount,
);
if (!allOutputsCovered) {
throw new Error('Not enough inputs to cover the outputs');
}
return new UnsignedTx(
new ExportTx(
baseTxUnsafeAvm(context, changeOutputs, inputs, memo),
Id.fromString(destinationChain),
outputs,
),
inputUtxos,
sigMappings,
);
};
Выполнить команду
Для локальной разработки. Не используйте в интернете!