@c4tplatform/caminojs
Version:
Camino Platform JS Library
722 lines • 129 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UTXOSet = exports.AssetAmountDestination = exports.UTXO = void 0;
/**
* @packageDocumentation
* @module API-AVM-UTXOs
*/
const buffer_1 = require("buffer/");
const bintools_1 = __importDefault(require("../../utils/bintools"));
const bn_js_1 = __importDefault(require("bn.js"));
const outputs_1 = require("./outputs");
const constants_1 = require("./constants");
const tx_1 = require("./tx");
const inputs_1 = require("./inputs");
const ops_1 = require("./ops");
const helperfunctions_1 = require("../../utils/helperfunctions");
const initialstates_1 = require("./initialstates");
const utxos_1 = require("../../common/utxos");
const createassettx_1 = require("./createassettx");
const operationtx_1 = require("./operationtx");
const basetx_1 = require("./basetx");
const exporttx_1 = require("./exporttx");
const importtx_1 = require("./importtx");
const constants_2 = require("../../utils/constants");
const assetamount_1 = require("../../common/assetamount");
const serialization_1 = require("../../utils/serialization");
const errors_1 = require("../../utils/errors");
/**
* @ignore
*/
const bintools = bintools_1.default.getInstance();
const serialization = serialization_1.Serialization.getInstance();
/**
* Class for representing a single UTXO.
*/
class UTXO extends utxos_1.StandardUTXO {
constructor() {
super(...arguments);
this._typeName = "UTXO";
this._typeID = undefined;
}
//serialize is inherited
deserialize(fields, encoding = "hex") {
super.deserialize(fields, encoding);
this.output = (0, outputs_1.SelectOutputClass)(fields["output"]["_typeID"]);
this.output.deserialize(fields["output"], encoding);
}
fromBuffer(bytes, offset = 0) {
this.codecID = bintools.copyFrom(bytes, offset, offset + 2);
offset += 2;
this.txid = bintools.copyFrom(bytes, offset, offset + 32);
offset += 32;
this.outputidx = bintools.copyFrom(bytes, offset, offset + 4);
offset += 4;
this.assetID = bintools.copyFrom(bytes, offset, offset + 32);
offset += 32;
const outputid = bintools
.copyFrom(bytes, offset, offset + 4)
.readUInt32BE(0);
offset += 4;
this.output = (0, outputs_1.SelectOutputClass)(outputid);
return this.output.fromBuffer(bytes, offset);
}
/**
* Takes a base-58 string containing a [[UTXO]], parses it, populates the class, and returns the length of the StandardUTXO in bytes.
*
* @param serialized A base-58 string containing a raw [[UTXO]]
*
* @returns The length of the raw [[UTXO]]
*
* @remarks
* unlike most fromStrings, it expects the string to be serialized in cb58 format
*/
fromString(serialized) {
/* istanbul ignore next */
return this.fromBuffer(bintools.cb58Decode(serialized));
}
/**
* Returns a base-58 representation of the [[UTXO]].
*
* @remarks
* unlike most toStrings, this returns in cb58 serialization format
*/
toString() {
/* istanbul ignore next */
return bintools.cb58Encode(this.toBuffer());
}
clone() {
const utxo = new UTXO();
utxo.fromBuffer(this.toBuffer());
return utxo;
}
create(codecID = constants_1.AVMConstants.LATESTCODEC, txid = undefined, outputidx = undefined, assetID = undefined, output = undefined) {
return new UTXO(codecID, txid, outputidx, assetID, output);
}
}
exports.UTXO = UTXO;
class AssetAmountDestination extends assetamount_1.StandardAssetAmountDestination {
}
exports.AssetAmountDestination = AssetAmountDestination;
/**
* Class representing a set of [[UTXO]]s.
*/
class UTXOSet extends utxos_1.StandardUTXOSet {
constructor() {
super(...arguments);
this._typeName = "UTXOSet";
this._typeID = undefined;
this.getMinimumSpendable = (aad, asOf = (0, helperfunctions_1.UnixNow)(), locktime = new bn_js_1.default(0), threshold = 1) => {
const utxoArray = this.getAllUTXOs();
const outids = {};
for (let i = 0; i < utxoArray.length && !aad.canComplete(); i++) {
const u = utxoArray[`${i}`];
const assetKey = u.getAssetID().toString("hex");
const fromAddresses = aad.getSenders();
if (u.getOutput() instanceof outputs_1.AmountOutput &&
aad.assetExists(assetKey) &&
u.getOutput().meetsThreshold(fromAddresses, asOf)) {
const am = aad.getAssetAmount(assetKey);
if (!am.isFinished()) {
const uout = u.getOutput();
outids[`${assetKey}`] = uout.getOutputID();
const amount = uout.getAmount();
am.spendAmount(amount);
const txid = u.getTxID();
const outputidx = u.getOutputIdx();
const input = new inputs_1.SECPTransferInput(amount);
const xferin = new inputs_1.TransferableInput(txid, outputidx, u.getAssetID(), input);
const spenders = uout.getSpenders(fromAddresses, asOf);
for (let j = 0; j < spenders.length; j++) {
const idx = uout.getAddressIdx(spenders[`${j}`]);
if (idx === -1) {
/* istanbul ignore next */
throw new errors_1.AddressError("Error - UTXOSet.getMinimumSpendable: no such " +
`address in output: ${spenders[`${j}`]}`);
}
xferin.getInput().addSignatureIdx(idx, spenders[`${j}`]);
}
aad.addInput(xferin);
}
else if (aad.assetExists(assetKey) &&
!(u.getOutput() instanceof outputs_1.AmountOutput)) {
/**
* Leaving the below lines, not simply for posterity, but for clarification.
* AssetIDs may have mixed OutputTypes.
* Some of those OutputTypes may implement AmountOutput.
* Others may not.
* Simply continue in this condition.
*/
/*return new Error('Error - UTXOSet.getMinimumSpendable: outputID does not '
+ `implement AmountOutput: ${u.getOutput().getOutputID}`)*/
continue;
}
}
}
if (!aad.canComplete()) {
return new errors_1.InsufficientFundsError("Error - UTXOSet.getMinimumSpendable: insufficient " +
"funds to create the transaction");
}
const amounts = aad.getAmounts();
const zero = new bn_js_1.default(0);
for (let i = 0; i < amounts.length; i++) {
const assetKey = amounts[`${i}`].getAssetIDString();
const amount = amounts[`${i}`].getAmount();
if (amount.gt(zero)) {
const spendout = (0, outputs_1.SelectOutputClass)(outids[`${assetKey}`], amount, aad.getDestinations(), locktime, threshold);
const xferout = new outputs_1.TransferableOutput(amounts[`${i}`].getAssetID(), spendout);
aad.addOutput(xferout);
}
const change = amounts[`${i}`].getChange();
if (change.gt(zero)) {
const changeout = (0, outputs_1.SelectOutputClass)(outids[`${assetKey}`], change, aad.getChangeAddresses());
const chgxferout = new outputs_1.TransferableOutput(amounts[`${i}`].getAssetID(), changeout);
aad.addChange(chgxferout);
}
}
return undefined;
};
/**
* Creates an [[UnsignedTx]] wrapping a [[BaseTx]]. For more granular control, you may create your own
* [[UnsignedTx]] wrapping a [[BaseTx]] manually (with their corresponding [[TransferableInput]]s and [[TransferableOutput]]s).
*
* @param networkID The number representing NetworkID of the node
* @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction
* @param amount The amount of the asset to be spent in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN}.
* @param assetID {@link https://github.com/feross/buffer|Buffer} of the asset ID for the UTXO
* @param toAddresses The addresses to send the funds
* @param fromAddresses The addresses being used to send the funds from the UTXOs {@link https://github.com/feross/buffer|Buffer}
* @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs. Default: toAddresses
* @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN}
* @param feeAssetID Optional. The assetID of the fees being burned. Default: assetID
* @param memo Optional. Contains arbitrary data, up to 256 bytes
* @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN}
* @param locktime Optional. The locktime field created in the resulting outputs
* @param toThreshold Optional. The number of signatures required to spend the funds in the resultant UTXO
* @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO
*
* @returns An unsigned transaction created from the passed in parameters.
*
*/
this.buildBaseTx = (networkID, blockchainID, amount, assetID, toAddresses, fromAddresses, changeAddresses = undefined, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), locktime = new bn_js_1.default(0), toThreshold = 1, changeThreshold = 1) => {
if (toThreshold > toAddresses.length) {
/* istanbul ignore next */
throw new errors_1.ThresholdError("Error - UTXOSet.buildBaseTx: threshold is greater than number of addresses");
}
if (typeof changeAddresses === "undefined") {
changeAddresses = toAddresses;
}
if (typeof feeAssetID === "undefined") {
feeAssetID = assetID;
}
const zero = new bn_js_1.default(0);
if (amount.eq(zero)) {
return undefined;
}
const aad = new AssetAmountDestination(toAddresses, toThreshold, fromAddresses, changeAddresses, changeThreshold);
if (assetID.toString("hex") === feeAssetID.toString("hex")) {
aad.addAssetAmount(assetID, amount, fee);
}
else {
aad.addAssetAmount(assetID, amount, zero);
if (this._feeCheck(fee, feeAssetID)) {
aad.addAssetAmount(feeAssetID, zero, fee);
}
}
let ins = [];
let outs = [];
const success = this.getMinimumSpendable(aad, asOf, locktime);
if (typeof success === "undefined") {
ins = aad.getInputs();
outs = aad.getAllOutputs();
}
else {
throw success;
}
const baseTx = new basetx_1.BaseTx(networkID, blockchainID, outs, ins, memo);
return new tx_1.UnsignedTx(baseTx);
};
/**
* Creates an unsigned Create Asset transaction. For more granular control, you may create your own
* [[CreateAssetTX]] manually (with their corresponding [[TransferableInput]]s, [[TransferableOutput]]s).
*
* @param networkID The number representing NetworkID of the node
* @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction
* @param fromAddresses The addresses being used to send the funds from the UTXOs {@link https://github.com/feross/buffer|Buffer}
* @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs
* @param initialState The [[InitialStates]] that represent the intial state of a created asset
* @param name String for the descriptive name of the asset
* @param symbol String for the ticker symbol of the asset
* @param denomination Optional number for the denomination which is 10^D. D must be >= 0 and <= 32. Ex: $1 AVAX = 10^9 $nAVAX
* @param mintOutputs Optional. Array of [[SECPMintOutput]]s to be included in the transaction. These outputs can be spent to mint more tokens.
* @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN}
* @param feeAssetID Optional. The assetID of the fees being burned.
* @param memo Optional contains arbitrary bytes, up to 256 bytes
* @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN}
* @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO
*
* @returns An unsigned transaction created from the passed in parameters.
*
*/
this.buildCreateAssetTx = (networkID, blockchainID, fromAddresses, changeAddresses, initialState, name, symbol, denomination, mintOutputs = undefined, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), changeThreshold = 1) => {
const zero = new bn_js_1.default(0);
let ins = [];
let outs = [];
if (this._feeCheck(fee, feeAssetID)) {
const aad = new AssetAmountDestination([], 0, fromAddresses, changeAddresses, changeThreshold);
aad.addAssetAmount(feeAssetID, zero, fee);
const success = this.getMinimumSpendable(aad, asOf);
if (typeof success === "undefined") {
ins = aad.getInputs();
outs = aad.getAllOutputs();
}
else {
throw success;
}
}
if (typeof mintOutputs !== "undefined") {
for (let i = 0; i < mintOutputs.length; i++) {
if (mintOutputs[`${i}`] instanceof outputs_1.SECPMintOutput) {
initialState.addOutput(mintOutputs[`${i}`]);
}
else {
throw new errors_1.SECPMintOutputError("Error - UTXOSet.buildCreateAssetTx: A submitted mintOutput was not of type SECPMintOutput");
}
}
}
let CAtx = new createassettx_1.CreateAssetTx(networkID, blockchainID, outs, ins, memo, name, symbol, denomination, initialState);
return new tx_1.UnsignedTx(CAtx);
};
/**
* Creates an unsigned Secp mint transaction. For more granular control, you may create your own
* [[OperationTx]] manually (with their corresponding [[TransferableInput]]s, [[TransferableOutput]]s, and [[TransferOperation]]s).
*
* @param networkID The number representing NetworkID of the node
* @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction
* @param mintOwner A [[SECPMintOutput]] which specifies the new set of minters
* @param transferOwner A [[SECPTransferOutput]] which specifies where the minted tokens will go
* @param fromAddresses The addresses being used to send the funds from the UTXOs {@link https://github.com/feross/buffer|Buffer}
* @param changeAddresses The addresses that can spend the change remaining from the spent UTXOs
* @param mintUTXOID The UTXOID for the [[SCPMintOutput]] being spent to produce more tokens
* @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN}
* @param feeAssetID Optional. The assetID of the fees being burned.
* @param memo Optional contains arbitrary bytes, up to 256 bytes
* @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN}
* @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO
*
* @returns An unsigned transaction created from the passed in parameters.
*/
this.buildSECPMintTx = (networkID, blockchainID, mintOwner, transferOwner, fromAddresses, changeAddresses, mintUTXOID, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), changeThreshold = 1) => {
const zero = new bn_js_1.default(0);
let ins = [];
let outs = [];
if (this._feeCheck(fee, feeAssetID)) {
const aad = new AssetAmountDestination([], 0, fromAddresses, changeAddresses, changeThreshold);
aad.addAssetAmount(feeAssetID, zero, fee);
const success = this.getMinimumSpendable(aad, asOf);
if (typeof success === "undefined") {
ins = aad.getInputs();
outs = aad.getAllOutputs();
}
else {
throw success;
}
}
let ops = [];
let mintOp = new ops_1.SECPMintOperation(mintOwner, transferOwner);
let utxo = this.getUTXO(mintUTXOID);
if (typeof utxo === "undefined") {
throw new errors_1.UTXOError("Error - UTXOSet.buildSECPMintTx: UTXOID not found");
}
if (utxo.getOutput().getOutputID() !== constants_1.AVMConstants.SECPMINTOUTPUTID) {
throw new errors_1.SECPMintOutputError("Error - UTXOSet.buildSECPMintTx: UTXO is not a SECPMINTOUTPUTID");
}
let out = utxo.getOutput();
let spenders = out.getSpenders(fromAddresses, asOf);
for (let j = 0; j < spenders.length; j++) {
let idx = out.getAddressIdx(spenders[`${j}`]);
if (idx == -1) {
/* istanbul ignore next */
throw new Error("Error - UTXOSet.buildSECPMintTx: no such address in output");
}
mintOp.addSignatureIdx(idx, spenders[`${j}`]);
}
let transferableOperation = new ops_1.TransferableOperation(utxo.getAssetID(), [`${mintUTXOID}`], mintOp);
ops.push(transferableOperation);
let operationTx = new operationtx_1.OperationTx(networkID, blockchainID, outs, ins, memo, ops);
return new tx_1.UnsignedTx(operationTx);
};
/**
* Creates an unsigned Create Asset transaction. For more granular control, you may create your own
* [[CreateAssetTX]] manually (with their corresponding [[TransferableInput]]s, [[TransferableOutput]]s).
*
* @param networkID The number representing NetworkID of the node
* @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction
* @param fromAddresses The addresses being used to send the funds from the UTXOs {@link https://github.com/feross/buffer|Buffer}
* @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs.
* @param minterSets The minters and thresholds required to mint this nft asset
* @param name String for the descriptive name of the nft asset
* @param symbol String for the ticker symbol of the nft asset
* @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN}
* @param feeAssetID Optional. The assetID of the fees being burned.
* @param memo Optional contains arbitrary bytes, up to 256 bytes
* @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN}
* @param locktime Optional. The locktime field created in the resulting mint output
* @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO
*
* @returns An unsigned transaction created from the passed in parameters.
*
*/
this.buildCreateNFTAssetTx = (networkID, blockchainID, fromAddresses, changeAddresses, minterSets, name, symbol, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), locktime = undefined, changeThreshold = 1) => {
const zero = new bn_js_1.default(0);
let ins = [];
let outs = [];
if (this._feeCheck(fee, feeAssetID)) {
const aad = new AssetAmountDestination([], 0, fromAddresses, changeAddresses, changeThreshold);
aad.addAssetAmount(feeAssetID, zero, fee);
const success = this.getMinimumSpendable(aad, asOf);
if (typeof success === "undefined") {
ins = aad.getInputs();
outs = aad.getAllOutputs();
}
else {
throw success;
}
}
let initialState = new initialstates_1.InitialStates();
for (let i = 0; i < minterSets.length; i++) {
let nftMintOutput = new outputs_1.NFTMintOutput(i, minterSets[`${i}`].getMinters(), locktime, minterSets[`${i}`].getThreshold());
initialState.addOutput(nftMintOutput, constants_1.AVMConstants.NFTFXID);
}
let denomination = 0; // NFTs are non-fungible
let CAtx = new createassettx_1.CreateAssetTx(networkID, blockchainID, outs, ins, memo, name, symbol, denomination, initialState);
return new tx_1.UnsignedTx(CAtx);
};
/**
* Creates an unsigned NFT mint transaction. For more granular control, you may create your own
* [[OperationTx]] manually (with their corresponding [[TransferableInput]]s, [[TransferableOutput]]s, and [[TransferOperation]]s).
*
* @param networkID The number representing NetworkID of the node
* @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction
* @param owners An array of [[OutputOwners]] who will be given the NFTs.
* @param fromAddresses The addresses being used to send the funds from the UTXOs
* @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs.
* @param utxoids An array of strings for the NFTs being transferred
* @param groupID Optional. The group this NFT is issued to.
* @param payload Optional. Data for NFT Payload.
* @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN}
* @param feeAssetID Optional. The assetID of the fees being burned.
* @param memo Optional contains arbitrary bytes, up to 256 bytes
* @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN}
* @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO
*
* @returns An unsigned transaction created from the passed in parameters.
*
*/
this.buildCreateNFTMintTx = (networkID, blockchainID, owners, fromAddresses, changeAddresses, utxoids, groupID = 0, payload = undefined, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), changeThreshold = 1) => {
const zero = new bn_js_1.default(0);
let ins = [];
let outs = [];
if (this._feeCheck(fee, feeAssetID)) {
const aad = new AssetAmountDestination([], 0, fromAddresses, changeAddresses, changeThreshold);
aad.addAssetAmount(feeAssetID, zero, fee);
const success = this.getMinimumSpendable(aad, asOf);
if (typeof success === "undefined") {
ins = aad.getInputs();
outs = aad.getAllOutputs();
}
else {
throw success;
}
}
let ops = [];
let nftMintOperation = new ops_1.NFTMintOperation(groupID, payload, owners);
for (let i = 0; i < utxoids.length; i++) {
let utxo = this.getUTXO(utxoids[`${i}`]);
let out = utxo.getOutput();
let spenders = out.getSpenders(fromAddresses, asOf);
for (let j = 0; j < spenders.length; j++) {
let idx;
idx = out.getAddressIdx(spenders[`${j}`]);
if (idx == -1) {
/* istanbul ignore next */
throw new errors_1.AddressError("Error - UTXOSet.buildCreateNFTMintTx: no such address in output");
}
nftMintOperation.addSignatureIdx(idx, spenders[`${j}`]);
}
let transferableOperation = new ops_1.TransferableOperation(utxo.getAssetID(), utxoids, nftMintOperation);
ops.push(transferableOperation);
}
let operationTx = new operationtx_1.OperationTx(networkID, blockchainID, outs, ins, memo, ops);
return new tx_1.UnsignedTx(operationTx);
};
/**
* Creates an unsigned NFT transfer transaction. For more granular control, you may create your own
* [[OperationTx]] manually (with their corresponding [[TransferableInput]]s, [[TransferableOutput]]s, and [[TransferOperation]]s).
*
* @param networkID The number representing NetworkID of the node
* @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction
* @param toAddresses An array of {@link https://github.com/feross/buffer|Buffer}s which indicate who recieves the NFT
* @param fromAddresses An array for {@link https://github.com/feross/buffer|Buffer} who owns the NFT
* @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs.
* @param utxoids An array of strings for the NFTs being transferred
* @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN}
* @param feeAssetID Optional. The assetID of the fees being burned.
* @param memo Optional contains arbitrary bytes, up to 256 bytes
* @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN}
* @param locktime Optional. The locktime field created in the resulting outputs
* @param toThreshold Optional. The number of signatures required to spend the funds in the resultant UTXO
* @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO
*
* @returns An unsigned transaction created from the passed in parameters.
*
*/
this.buildNFTTransferTx = (networkID, blockchainID, toAddresses, fromAddresses, changeAddresses, utxoids, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), locktime = new bn_js_1.default(0), toThreshold = 1, changeThreshold = 1) => {
const zero = new bn_js_1.default(0);
let ins = [];
let outs = [];
if (this._feeCheck(fee, feeAssetID)) {
const aad = new AssetAmountDestination([], 0, fromAddresses, changeAddresses, changeThreshold);
aad.addAssetAmount(feeAssetID, zero, fee);
const success = this.getMinimumSpendable(aad, asOf);
if (typeof success === "undefined") {
ins = aad.getInputs();
outs = aad.getAllOutputs();
}
else {
throw success;
}
}
const ops = [];
for (let i = 0; i < utxoids.length; i++) {
const utxo = this.getUTXO(utxoids[`${i}`]);
const out = utxo.getOutput();
const spenders = out.getSpenders(fromAddresses, asOf);
const outbound = new outputs_1.NFTTransferOutput(out.getGroupID(), out.getPayload(), toAddresses, locktime, toThreshold);
const op = new ops_1.NFTTransferOperation(outbound);
for (let j = 0; j < spenders.length; j++) {
const idx = out.getAddressIdx(spenders[`${j}`]);
if (idx === -1) {
/* istanbul ignore next */
throw new errors_1.AddressError("Error - UTXOSet.buildNFTTransferTx: " +
`no such address in output: ${spenders[`${j}`]}`);
}
op.addSignatureIdx(idx, spenders[`${j}`]);
}
const xferop = new ops_1.TransferableOperation(utxo.getAssetID(), [utxoids[`${i}`]], op);
ops.push(xferop);
}
const OpTx = new operationtx_1.OperationTx(networkID, blockchainID, outs, ins, memo, ops);
return new tx_1.UnsignedTx(OpTx);
};
/**
* Creates an unsigned ImportTx transaction.
*
* @param networkID The number representing NetworkID of the node
* @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction
* @param toAddresses The addresses to send the funds
* @param fromAddresses The addresses being used to send the funds from the UTXOs {@link https://github.com/feross/buffer|Buffer}
* @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs.
* @param importIns An array of [[TransferableInput]]s being imported
* @param sourceChain A {@link https://github.com/feross/buffer|Buffer} for the chainid where the imports are coming from.
* @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN}. Fee will come from the inputs first, if they can.
* @param feeAssetID Optional. The assetID of the fees being burned.
* @param memo Optional contains arbitrary bytes, up to 256 bytes
* @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN}
* @param locktime Optional. The locktime field created in the resulting outputs
* @param toThreshold Optional. The number of signatures required to spend the funds in the resultant UTXO
* @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO
*
* @returns An unsigned transaction created from the passed in parameters.
*
*/
this.buildImportTx = (networkID, blockchainID, toAddresses, fromAddresses, changeAddresses, atomics, sourceChain = undefined, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), locktime = new bn_js_1.default(0), toThreshold = 1, changeThreshold = 1) => {
const zero = new bn_js_1.default(0);
let ins = [];
let outs = [];
if (typeof fee === "undefined") {
fee = zero.clone();
}
const importIns = [];
let feepaid = new bn_js_1.default(0);
let feeAssetStr = feeAssetID.toString("hex");
for (let i = 0; i < atomics.length; i++) {
const utxo = atomics[`${i}`];
const assetID = utxo.getAssetID();
const output = utxo.getOutput();
let amt = output.getAmount().clone();
let infeeamount = amt.clone();
let assetStr = assetID.toString("hex");
if (typeof feeAssetID !== "undefined" &&
fee.gt(zero) &&
feepaid.lt(fee) &&
assetStr === feeAssetStr) {
feepaid = feepaid.add(infeeamount);
if (feepaid.gt(fee)) {
infeeamount = feepaid.sub(fee);
feepaid = fee.clone();
}
else {
infeeamount = zero.clone();
}
}
const txid = utxo.getTxID();
const outputidx = utxo.getOutputIdx();
const input = new inputs_1.SECPTransferInput(amt);
const xferin = new inputs_1.TransferableInput(txid, outputidx, assetID, input);
const from = output.getAddresses();
const spenders = output.getSpenders(from, asOf);
for (let j = 0; j < spenders.length; j++) {
const idx = output.getAddressIdx(spenders[`${j}`]);
if (idx === -1) {
/* istanbul ignore next */
throw new errors_1.AddressError("Error - UTXOSet.buildImportTx: no such " +
`address in output: ${spenders[`${j}`]}`);
}
xferin.getInput().addSignatureIdx(idx, spenders[`${j}`]);
}
importIns.push(xferin);
//add extra outputs for each amount (calculated from the imported inputs), minus fees
if (infeeamount.gt(zero)) {
const spendout = (0, outputs_1.SelectOutputClass)(output.getOutputID(), infeeamount, toAddresses, locktime, toThreshold);
const xferout = new outputs_1.TransferableOutput(assetID, spendout);
outs.push(xferout);
}
}
// get remaining fees from the provided addresses
let feeRemaining = fee.sub(feepaid);
if (feeRemaining.gt(zero) && this._feeCheck(feeRemaining, feeAssetID)) {
const aad = new AssetAmountDestination(toAddresses, toThreshold, fromAddresses, changeAddresses, changeThreshold);
aad.addAssetAmount(feeAssetID, zero, feeRemaining);
const success = this.getMinimumSpendable(aad, asOf, locktime);
if (typeof success === "undefined") {
ins = aad.getInputs();
outs = aad.getAllOutputs();
}
else {
throw success;
}
}
const importTx = new importtx_1.ImportTx(networkID, blockchainID, outs, ins, memo, sourceChain, importIns);
return new tx_1.UnsignedTx(importTx);
};
/**
* Creates an unsigned ExportTx transaction.
*
* @param networkID The number representing NetworkID of the node
* @param blockchainID The {@link https://github.com/feross/buffer|Buffer} representing the BlockchainID for the transaction
* @param amount The amount being exported as a {@link https://github.com/indutny/bn.js/|BN}
* @param avaxAssetID {@link https://github.com/feross/buffer|Buffer} of the asset ID for AVAX
* @param toAddresses An array of addresses as {@link https://github.com/feross/buffer|Buffer} who recieves the AVAX
* @param fromAddresses An array of addresses as {@link https://github.com/feross/buffer|Buffer} who owns the AVAX
* @param changeAddresses Optional. The addresses that can spend the change remaining from the spent UTXOs.
* @param fee Optional. The amount of fees to burn in its smallest denomination, represented as {@link https://github.com/indutny/bn.js/|BN}
* @param destinationChain Optional. A {@link https://github.com/feross/buffer|Buffer} for the chainid where to send the asset.
* @param feeAssetID Optional. The assetID of the fees being burned.
* @param memo Optional contains arbitrary bytes, up to 256 bytes
* @param asOf Optional. The timestamp to verify the transaction against as a {@link https://github.com/indutny/bn.js/|BN}
* @param locktime Optional. The locktime field created in the resulting outputs
* @param toThreshold Optional. The number of signatures required to spend the funds in the resultant UTXO
* @param changethreshold Optional. The number of signatures required to spend the funds in the resultant change UTXO
*
* @returns An unsigned transaction created from the passed in parameters.
*
*/
this.buildExportTx = (networkID, blockchainID, amount, assetID, toAddresses, fromAddresses, changeAddresses = undefined, destinationChain = undefined, fee = undefined, feeAssetID = undefined, memo = undefined, asOf = (0, helperfunctions_1.UnixNow)(), locktime = new bn_js_1.default(0), toThreshold = 1, changeThreshold = 1) => {
let ins = [];
let outs = [];
let exportouts = [];
if (typeof changeAddresses === "undefined") {
changeAddresses = toAddresses;
}
const zero = new bn_js_1.default(0);
if (amount.eq(zero)) {
return undefined;
}
if (typeof feeAssetID === "undefined") {
feeAssetID = assetID;
}
if (typeof destinationChain === "undefined") {
destinationChain = bintools.cb58Decode(constants_2.DefaultPlatformChainID);
}
const aad = new AssetAmountDestination(toAddresses, toThreshold, fromAddresses, changeAddresses, changeThreshold);
if (assetID.toString("hex") === feeAssetID.toString("hex")) {
aad.addAssetAmount(assetID, amount, fee);
}
else {
aad.addAssetAmount(assetID, amount, zero);
if (this._feeCheck(fee, feeAssetID)) {
aad.addAssetAmount(feeAssetID, zero, fee);
}
}
const success = this.getMinimumSpendable(aad, asOf, locktime);
if (typeof success === "undefined") {
ins = aad.getInputs();
outs = aad.getChangeOutputs();
exportouts = aad.getOutputs();
}
else {
throw success;
}
const exportTx = new exporttx_1.ExportTx(networkID, blockchainID, outs, ins, memo, destinationChain, exportouts);
return new tx_1.UnsignedTx(exportTx);
};
}
//serialize is inherited
deserialize(fields, encoding = "hex") {
super.deserialize(fields, encoding);
let utxos = {};
for (let utxoid in fields["utxos"]) {
let utxoidCleaned = serialization.decoder(utxoid, encoding, "base58", "base58");
utxos[`${utxoidCleaned}`] = new UTXO();
utxos[`${utxoidCleaned}`].deserialize(fields["utxos"][`${utxoid}`], encoding);
}
let addressUTXOs = {};
for (let address in fields["addressUTXOs"]) {
let addressCleaned = serialization.decoder(address, encoding, "cb58", "hex");
let utxobalance = {};
for (let utxoid in fields["addressUTXOs"][`${address}`]) {
let utxoidCleaned = serialization.decoder(utxoid, encoding, "base58", "base58");
utxobalance[`${utxoidCleaned}`] = serialization.decoder(fields["addressUTXOs"][`${address}`][`${utxoid}`], encoding, "decimalString", "BN");
}
addressUTXOs[`${addressCleaned}`] = utxobalance;
}
this.utxos = utxos;
this.addressUTXOs = addressUTXOs;
}
parseUTXO(utxo) {
const utxovar = new UTXO();
// force a copy
if (typeof utxo === "string") {
utxovar.fromBuffer(bintools.cb58Decode(utxo));
}
else if (utxo instanceof UTXO) {
utxovar.fromBuffer(utxo.toBuffer()); // forces a copy
}
else {
/* istanbul ignore next */
throw new errors_1.UTXOError("Error - UTXO.parseUTXO: utxo parameter is not a UTXO or string");
}
return utxovar;
}
create() {
return new UTXOSet();
}
clone() {
const newset = this.create();
const allUTXOs = this.getAllUTXOs();
newset.addArray(allUTXOs);
return newset;
}
_feeCheck(fee, feeAssetID) {
return (typeof fee !== "undefined" &&
typeof feeAssetID !== "undefined" &&
fee.gt(new bn_js_1.default(0)) &&
feeAssetID instanceof buffer_1.Buffer);
}
}
exports.UTXOSet = UTXOSet;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXR4b3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpcy9hdm0vdXR4b3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7OztHQUdHO0FBQ0gsb0NBQWdDO0FBQ2hDLG9FQUEyQztBQUMzQyxrREFBc0I7QUFDdEIsdUNBUWtCO0FBQ2xCLDJDQUEwQztBQUMxQyw2QkFBaUM7QUFDakMscUNBQStEO0FBQy9ELCtCQUtjO0FBRWQsaUVBQXFEO0FBQ3JELG1EQUErQztBQUUvQyw4Q0FBa0U7QUFDbEUsbURBQStDO0FBQy9DLCtDQUEyQztBQUMzQyxxQ0FBaUM7QUFDakMseUNBQXFDO0FBQ3JDLHlDQUFxQztBQUNyQyxxREFBOEQ7QUFDOUQsMERBR2lDO0FBQ2pDLDZEQUE2RTtBQUM3RSwrQ0FNMkI7QUFFM0I7O0dBRUc7QUFDSCxNQUFNLFFBQVEsR0FBYSxrQkFBUSxDQUFDLFdBQVcsRUFBRSxDQUFBO0FBQ2pELE1BQU0sYUFBYSxHQUFrQiw2QkFBYSxDQUFDLFdBQVcsRUFBRSxDQUFBO0FBRWhFOztHQUVHO0FBQ0gsTUFBYSxJQUFLLFNBQVEsb0JBQVk7SUFBdEM7O1FBQ1ksY0FBUyxHQUFHLE1BQU0sQ0FBQTtRQUNsQixZQUFPLEdBQUcsU0FBUyxDQUFBO0lBb0UvQixDQUFDO0lBbEVDLHdCQUF3QjtJQUV4QixXQUFXLENBQUMsTUFBYyxFQUFFLFdBQStCLEtBQUs7UUFDOUQsS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUE7UUFDbkMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFBLDJCQUFpQixFQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFBO1FBQzVELElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQTtJQUNyRCxDQUFDO0lBRUQsVUFBVSxDQUFDLEtBQWEs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