<commit_before>import {xdr, Keypair, Hyper, UnsignedHyper, hash, encodeBase58Check} from "stellar-base";

import {Account} from "./account";
import {Currency} from "./currency";
import {best_r} from "./util/continued_fraction";

/**
* @class Operation
*/
export class Operation {

    /**
    * Create and fund a non existent account.
    * @param {object} opts
    * @param {string} opts.destination - Destination address to create an account for.
    * @param {string} opts.startingBalance - Amount the account should be funded. Must be greater
    *                                   than the reserve balance amount.
    * @param {string} [opts.source] - The source account for the payment. Defaults to the transaction's source account.
    * @returns {xdr.CreateAccountOp}
    */
    static createAccount(opts) {
        if (!opts.destination) {
            throw new Error("Must provide a destination for a payment operation");
        }
        if (!opts.startingBalance) {
            throw new Error("Must provide a starting balance");
        }
        let attributes = {};
        attributes.destination  = Keypair.fromAddress(opts.destination).publicKey();
        attributes.startingBalance = Hyper.fromString(String(opts.startingBalance));
        let createAccount = new xdr.CreateAccountOp(attributes);

        let opAttributes = {};
        opAttributes.body = xdr.OperationBody.createAccount(createAccount);
        if (opts.source) {
            opAttributes.sourceAccount = Keypair.fromAddress(opts.source).publicKey();
        }
        let op = new xdr.Operation(opAttributes);
        return op;
    }

    /**
    * Create a payment operation.
    * @param {object} opts
    * @param {string} opts.destination - The destination address.
    * @param {Currency} opts.currency - The currency to send.
    * @param {string} opts.amount - The amount to send.
    * @param {string} [opts.source] - The source account for the payment. Defaults to the transaction's source account.
    * @returns {xdr.PaymentOp}
    */
    static payment(opts) {
        if (!opts.destination) {
            throw new Error("Must provide a destination for a payment operation");
        }
        if (!opts.currency) {
            throw new Error("Must provide a currency for a payment operation");
        }
        if (!opts.amount) {
            throw new Error("Must provide an amount for a payment operation");
        }

        let attributes = {};
        attributes.destination  = Keypair.fromAddress(opts.destination).publicKey();
        attributes.currency     = opts.currency.toXdrObject();
        attributes.amount       = Hyper.fromString(String(opts.amount));
        let payment = new xdr.PaymentOp(attributes);

        let opAttributes = {};
        opAttributes.body = xdr.OperationBody.payment(payment);
        if (opts.source) {
            opAttributes.sourceAccount = Keypair.fromAddress(opts.source).publicKey();
        }
        let op = new xdr.Operation(opAttributes);
        return op;
    }

    /**
    * Returns a XDR PaymentOp. A "payment" operation send the specified amount to the
    * destination account, optionally through a path. XLM payments create the destination
    * account if it does not exist.
    * @param {object} opts
    * @param {Currency} opts.sendCurrency - The currency to pay with.
    * @param {string} opts.sendMax - The maximum amount of sendCurrency to send.
    * @param {string} opts.destination - The destination account to send to.
    * @param {Currency} opts.destCurrency - The currency the destination will receive.
    * @param {string|number} otps.destAmount - The amount the destination receives.
    * @param {array} [opts.path] - An array of Currency objects to use as the path.
    * @param {string} [opts.source] - The source account for the payment. Defaults to the transaction's source account.
    * @returns {xdr.PathPaymentOp}
    */
    static pathPayment(opts) {
        if (!opts.sendCurrency) {
            throw new Error("Must specify a send currency");
        }
        if (!opts.sendMax) {
            throw new Error("Must specify a send max");
        }
        if (!opts.destination) {
            throw new Error("Must provide a destination for a payment operation");
        }
        if (!opts.destCurrency) {
            throw new Error("Must provide a destCurrency for a payment operation");
        }
        if (!opts.destAmount) {
            throw new Error("Must provide an destAmount for a payment operation");
        }


        let attributes = {};
        attributes.sendCurrency = opts.sendCurrency.toXdrObject();
        attributes.sendMax      = Hyper.fromString(String(opts.sendMax));
        attributes.destination  = Keypair.fromAddress(opts.destination).publicKey();
        attributes.destCurrency = opts.destCurrency.toXdrObject();
        attributes.destAmount       = Hyper.fromString(String(opts.destAmount));
        attributes.path         = opts.path ? opts.path : [];
        let payment = new xdr.PathPaymentOp(attributes);

        let opAttributes = {};
        opAttributes.body = xdr.OperationBody.pathPayment(payment);
        if (opts.source) {
            opAttributes.sourceAccount = Keypair.fromAddress(opts.source).publicKey();
        }
        let op = new xdr.Operation(opAttributes);
        return op;
    }

    /**
    * Returns an XDR ChangeTrustOp. A "change trust" operation adds, removes, or updates a
    * trust line for a given currency from the source account to another. The issuer being
    * trusted and the currency code are in the given Currency object.
    * @param {object} opts
    * @param {Currency} opts.currency - The currency for the trust line.
    * @param {string} [opts.limit] - The limit for the currency, defaults to max int64.
    *                                If the limit is set to 0 it deletes the trustline.
    * @param {string} [opts.source] - The source account (defaults to transaction source).
    * @returns {xdr.ChangeTrustOp}
    */
    static changeTrust(opts) {
        let attributes      = {};
        attributes.line     = opts.currency.toXdrObject();
        let limit           = opts.limit ? limit : "9223372036854775807";
        attributes.limit    = Hyper.fromString(limit);
        if (opts.source) {
            attributes.source   = opts.source ? opts.source.masterKeypair : null;
        }
        let changeTrustOP = new xdr.ChangeTrustOp(attributes);

        let opAttributes = {};
        opAttributes.body = xdr.OperationBody.changeTrust(changeTrustOP);
        if (opts.source) {
            opAttributes.sourceAccount = Keypair.fromAddress(opts.source).publicKey();
        }
        let op = new xdr.Operation(opAttributes);
        return op;
    }

    /**
    * Returns an XDR AllowTrustOp. An "allow trust" operation authorizes another
    * account to hold your account's credit for a given currency.
    * @param {object} opts
    * @param {string} opts.trustor - The trusting account (the one being authorized)
    * @param {string} opts.currencyCode - The currency code being authorized.
    * @param {boolean} opts.authorize - True to authorize the line, false to deauthorize.
    * @param {string} [opts.source] - The source account (defaults to transaction source).
    * @returns {xdr.AllowTrustOp}
    */
    static allowTrust(opts) {
        let attributes = {};
        attributes.trustor = Keypair.fromAddress(opts.trustor).publicKey();
        let code = opts.currencyCode.length == 3 ? opts.currencyCode + "\0" : opts.currencyCode;
        attributes.currency = xdr.AllowTrustOpCurrency.currencyTypeAlphanum(code);
        attributes.authorize = opts.authorize;
        let allowTrustOp = new xdr.AllowTrustOp(attributes);

        let opAttributes = {};
        opAttributes.body = xdr.OperationBody.allowTrust(allowTrustOp);
        if (opts.source) {
            opAttributes.sourceAccount = Keypair.fromAddress(opts.source).publicKey();
        }
        let op = new xdr.Operation(opAttributes);
        return op;
    }

    /**
    * Returns an XDR SetOptionsOp. A "set options" operations set or clear account flags,
    * set the account's inflation destination, and/or add new signers to the account.
    * TODO: implement
    * @param {object} opts
    * @param {string} [opts.inflationDest] - Set this address as the account's inflation destination.
    * @param {number} [opts.clearFlags] - Bitmap integer for which flags to clear.
    * @param {number} [opts.setFlags] - Bitmap integer for which flags to set.
    * @param {array} [opts.thresholds] - Sets the weight of the master key and the threshold<commit_msg>Update operation docs<commit_after>import {xdr, Keypair, Hyper, UnsignedHyper, hash, encodeBase58Check} from "stellar-base";

import {Account} from "./account";
import {Currency} from "./currency";
import {best_r} from "./util/continued_fraction";

/**
* @class Operation
*/
export class Operation {

    /**
    * Create and fund a non existent account.
    * @param {object} opts
    * @param {string} opts.destination - Destination address to create an account for.
    * @param {string} opts.startingBalance - Amount the account should be funded. Must be greater
    *                                   than the reserve balance amount.
    * @param {string} [opts.source] - The source account for the payment. Defaults to the transaction's source account.
    * @returns {xdr.CreateAccountOp}
    */
    static createAccount(opts) {
        if (!opts.destination) {
            throw new Error("Must provide a destination for a payment operation");
        }
        if (!opts.startingBalance) {
            throw new Error("Must provide a starting balance");
        }
        let attributes = {};
        attributes.destination  = Keypair.fromAddress(opts.destination).publicKey();
        attributes.startingBalance = Hyper.fromString(String(opts.startingBalance));
        let createAccount = new xdr.CreateAccountOp(attributes);

        let opAttributes = {};
        opAttributes.body = xdr.OperationBody.createAccount(createAccount);
        if (opts.source) {
            opAttributes.sourceAccount = Keypair.fromAddress(opts.source).publicKey();
        }
        let op = new xdr.Operation(opAttributes);
        return op;
    }

    /**
    * Create a payment operation.
    * @param {object} opts
    * @param {string} opts.destination - The destination address.
    * @param {Currency} opts.currency - The currency to send.
    * @param {string} opts.amount - The amount to send.
    * @param {string} [opts.source] - The source account for the payment. Defaults to the transaction's source account.
    * @returns {xdr.PaymentOp}
    */
    static payment(opts) {
        if (!opts.destination) {
            throw new Error("Must provide a destination for a payment operation");
        }
        if (!opts.currency) {
            throw new Error("Must provide a currency for a payment operation");
        }
        if (!opts.amount) {
            throw new Error("Must provide an amount for a payment operation");
        }

        let attributes = {};
        attributes.destination  = Keypair.fromAddress(opts.destination).publicKey();
        attributes.currency     = opts.currency.toXdrObject();
        attributes.amount       = Hyper.fromString(String(opts.amount));
        let payment = new xdr.PaymentOp(attributes);

        let opAttributes = {};
        opAttributes.body = xdr.OperationBody.payment(payment);
        if (opts.source) {
            opAttributes.sourceAccount = Keypair.fromAddress(opts.source).publicKey();
        }
        let op = new xdr.Operation(opAttributes);
        return op;
    }

    /**
    * Returns a XDR PaymentOp. A "payment" operation send the specified amount to the
    * destination account, optionally through a path. XLM payments create the destination
    * account if it does not exist.
    * @param {object} opts
    * @param {Currency} opts.sendCurrency - The currency to pay with.
    * @param {string} opts.sendMax - The maximum amount of sendCurrency to send.
    * @param {string} opts.destination - The destination account to send to.
    * @param {Currency} opts.destCurrency - The currency the destination will receive.
    * @param {string|number} otps.destAmount - The amount the destination receives.
    * @param {array} [opts.path] - An array of Currency objects to use as the path.
    * @param {string} [opts.source] - The source account for the payment. Defaults to the transaction's source account.
    * @returns {xdr.PathPaymentOp}
    */
    static pathPayment(opts) {
        if (!opts.sendCurrency) {
            throw new Error("Must specify a send currency");
        }
        if (!opts.sendMax) {
            throw new Error("Must specify a send max");
        }
        if (!opts.destination) {
            throw new Error("Must provide a destination for a payment operation");
        }
        if (!opts.destCurrency) {
            throw new Error("Must provide a destCurrency for a payment operation");
        }
        if (!opts.destAmount) {
            throw new Error("Must provide an destAmount for a payment operation");
        }


        let attributes = {};
        attributes.sendCurrency = opts.sendCurrency.toXdrObject();
        attributes.sendMax      = Hyper.fromString(String(opts.sendMax));
        attributes.destination  = Keypair.fromAddress(opts.destination).publicKey();
        attributes.destCurrency = opts.destCurrency.toXdrObject();
        attributes.destAmount       = Hyper.fromString(String(opts.destAmount));
        attributes.path         = opts.path ? opts.path : [];
        let payment = new xdr.PathPaymentOp(attributes);

        let opAttributes = {};
        opAttributes.body = xdr.OperationBody.pathPayment(payment);
        if (opts.source) {
            opAttributes.sourceAccount = Keypair.fromAddress(opts.source).publicKey();
        }
        let op = new xdr.Operation(opAttributes);
        return op;
    }

    /**
    * Returns an XDR ChangeTrustOp. A "change trust" operation adds, removes, or updates a
    * trust line for a given currency from the source account to another. The issuer being
    * trusted and the currency code are in the given Currency object.
    * @param {object} opts
    * @param {Currency} opts.currency - The currency for the trust line.
    * @param {string} [opts.limit] - The limit for the currency, defaults to max int64.
    *                                If the limit is set to 0 it deletes the trustline.
    * @param {string} [opts.source] - The source account (defaults to transaction source).
    * @returns {xdr.ChangeTrustOp}
    */
    static changeTrust(opts) {
        let attributes      = {};
        attributes.line     = opts.currency.toXdrObject();
        let limit           = opts.limit ? limit : "9223372036854775807";
        attributes.limit    = Hyper.fromString(limit);
        if (opts.source) {
            attributes.source   = opts.source ? opts.source.masterKeypair : null;
        }
        let changeTrustOP = new xdr.ChangeTrustOp(attributes);

        let opAttributes = {};
        opAttributes.body = xdr.OperationBody.changeTrust(changeTrustOP);
        if (opts.source) {
            opAttributes.sourceAccount = Keypair.fromAddress(opts.source).publicKey();
        }
        let op = new xdr.Operation(opAttributes);
        return op;
    }

    /**
    * Returns an XDR AllowTrustOp. An "allow trust" operation authorizes another
    * account to hold your account's credit for a given currency.
    * @param {object} opts
    * @param {string} opts.trustor - The trusting account (the one being authorized)
    * @param {string} opts.currencyCode - The currency code being authorized.
    * @param {boolean} opts.authorize - True to authorize the line, false to deauthorize.
    * @param {string} [opts.source] - The source account (defaults to transaction source).
    * @returns {xdr.AllowTrustOp}
    */
    static allowTrust(opts) {
        let attributes = {};
        attributes.trustor = Keypair.fromAddress(opts.trustor).publicKey();
        let code = opts.currencyCode.length == 3 ? opts.currencyCode + "\0" : opts.currencyCode;
        attributes.currency = xdr.AllowTrustOpCurrency.currencyTypeAlphanum(code);
        attributes.authorize = opts.authorize;
        let allowTrustOp = new xdr.AllowTrustOp(attributes);

        let opAttributes = {};
        opAttributes.body = xdr.OperationBody.allowTrust(allowTrustOp);
        if (opts.source) {
            opAttributes.sourceAccount = Keypair.fromAddress(opts.source).publicKey();
        }
        let op = new xdr.Operation(opAttributes);
        return op;
    }

    /**
    * Returns an XDR SetOptionsOp. A "set options" operations set or clear account flags,
    * set the account's inflation destination, and/or add new signers to the account.
    * The account flags are the xdr.AccountFlags enum, which are:
    *   - AUTH_REQUIRED_FLAG = 0x1
    *   - AUTH_REVOCABLE_FLAG = 0x2
    * @param {object} opts
    * @param {string} [opts.inflationDest] - Set this address as the account's inflation destination.
    * @param {number} [opts.clearFlags] - Bitmap integer for which flags to clear.
    * @param {number} [opts.setFlags] - Bitmap integer for which flags to set.
    * @param {array} [opts.thresholds] - Sets the weight of the master key and the threshold
{'fraction_non_alphanumeric': 0.10103790354951546, 'fraction_numerical': 0.003211193302368255, 'mean_word_length': 2.5715748515257015, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1254789', 'n_tokens_mistral': 4708, 'n_tokens_neox': 4573, 'n_words': 1466}