import { tx, wallet, u } from "@cityofzion/neon-core";
/**
 * A class with functions to sign transaction
 */
export class TransactionSigner {
    constructor(transaction) {
        this.transaction = transaction;
    }
    /**
     * Sign a transaction with Accounts or Private Keys.
     * This is used when you have full access to signer accounts
     * @param accounts - accounts that will sign this transaction
     */
    signWithAccount(...accounts) {
        accounts.forEach((account) => {
            this._checkAcc(account);
            this.transaction.sign(account);
        });
    }
    /**
     * Sign a transaction with Witnesses.
     * This can be used when you accept a signature from someone else
     * @param witnesses - witnesses that will be added to the transaction
     */
    signWithWitness(...witnesses) {
        witnesses.forEach((witness) => {
            this._checkWitness(witness);
            this.transaction.addWitness(witness);
        });
    }
    /**
     * Sign a transaction with multi-signatures for multi-sig account
     * @param multisigAccount - multisig account
     * @param witnesses - signatures from accounts within the multisig-account
     */
    signWithMultiSigAccount(multisigAccount, ...witnesses) {
        this._checkMultisigAcc(multisigAccount);
        const multisigWitness = tx.Witness.buildMultiSig(this.transaction.serialize(), witnesses, multisigAccount);
        this.transaction.addWitness(multisigWitness);
    }
    _checkAcc(account) {
        const acc = new wallet.Account(account);
        this._assertShouldSign(acc.scriptHash);
    }
    _checkWitness(witness) {
        this._assertShouldSign(u.reverseHex(u.hash160(witness.verificationScript.toBigEndian())));
    }
    _checkMultisigAcc(multisigAcc) {
        if (!multisigAcc.isMultiSig) {
            throw new Error(`${multisigAcc} is not a multi-sig account or cannot get verificationScript from it`);
        }
        this._assertShouldSign(multisigAcc.scriptHash);
    }
    _getSignerHashes() {
        return [
            this.transaction.sender,
            ...this.transaction.signers.map((cosigner) => cosigner.account),
        ].map((hash) => u.reverseHex(hash.toBigEndian()));
    }
    _assertShouldSign(scriptHash) {
        if (!this._getSignerHashes().some((hash) => hash === scriptHash)) {
            throw new Error(`account with scripthash: ${scriptHash} is neither sender nor cosigner`);
        }
    }
}
//# sourceMappingURL=signer.js.map