"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_browserify_1 = require("crypto-browserify");
const byzcoin_1 = require("../../../byzcoin");
const darc_1 = require("../../../darc");
const _1 = require("./");
/**
 * DarcContract represents a darc taken from an instance. It has all necessary constants to interact with a darc
 * contract on byzcoin.
 */
exports.contractID = "darc";
exports.commandEvolve = "evolve";
exports.commandEvolveUnrestricted = "evolve_unrestricted";
exports.argumentDarc = "darc";
exports.ruleSign = darc_1.Darc.ruleSign;
exports.ruleEvolve = "invoke:" + exports.contractID + "." + exports.commandEvolve;
exports.ruleEvolveUnrestricted = "invoke:" + exports.contractID + "." +
    exports.commandEvolveUnrestricted;
/**
 * Creates an instruction in the transaction with either an update of the description and/or an update
 * of the rules.
 *
 * @param tx where the instruction will be appended to
 * @param oldDarc that needs to be evolved
 * @param updates contains a description update and/or rules to be merged
 * @param unrestricted if true, will create an unrestricted evolve that allows to create new rules
 * @return the new DARC as it will appear on ByzCoin if the transaction is accepted
 */
function evolve(tx, oldDarc, updates, unrestricted = false) {
    const newArgs = Object.assign(Object.assign({}, oldDarc.evolve()), updates);
    const newDarc = new darc_1.Darc(newArgs);
    const cmd = unrestricted ? exports.commandEvolveUnrestricted : exports.commandEvolve;
    const args = [new byzcoin_1.Argument({
            name: exports.argumentDarc,
            value: Buffer.from(darc_1.Darc.encode(newDarc).finish()),
        })];
    tx.invoke(newDarc.getBaseID(), exports.contractID, cmd, args);
    return newDarc;
}
exports.evolve = evolve;
/**
 * Creates the instruction necessary to spawn a new coin using this darc.
 *
 * @param tx where the instruction will be appended to
 * @param did baseID of the darc that can spawn coins
 * @param name of the coin
 * @param preHash used to calculate the ID of the coin, if given
 */
function spawnCoin(tx, did, name, preHash) {
    if (preHash === undefined) {
        preHash = crypto_browserify_1.randomBytes(32);
    }
    const args = [new byzcoin_1.Argument({ name: _1.CoinContract.argumentType, value: name }),
        new byzcoin_1.Argument({ name: _1.CoinContract.argumentCoinID, value: preHash })];
    tx.spawn(did, _1.CoinContract.contractID, args);
    return _1.CoinContract.coinIID(preHash);
}
exports.spawnCoin = spawnCoin;
/**
 * Spawns a new darc. The darc given by did must have a `spawn:darc` rule.
 *
 * @param tx where the instruction will be appended to
 * @param did baseID of the darc that can spawn other darcs
 * @param newDarc to be spawned
 */
function spawnDarc(tx, did, newDarc) {
    tx.spawn(did, exports.contractID, [new byzcoin_1.Argument({ name: exports.argumentDarc, value: newDarc.toBytes() })]);
}
exports.spawnDarc = spawnDarc;
