"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getOperatorContract = exports.transferTokens = exports.sponsor = exports.unstake = exports.stake = exports.undelegate = exports.delegate = void 0;
exports.deployOperatorContract = deployOperatorContract;
exports.deploySponsorshipContract = deploySponsorshipContract;
const config_1 = require("@streamr/config");
const network_contracts_1 = require("@streamr/network-contracts");
const utils_1 = require("@streamr/utils");
const ethers_1 = require("ethers");
const FRACTION_MAX = (0, ethers_1.parseEther)('1');
const logger = new utils_1.Logger(module);
/**
 * @param opts.deployer should be the operator's Wallet
 * @returns Operator
 */
async function deployOperatorContract(opts) {
    logger.debug('Deploying OperatorContract');
    const operatorFactory = new ethers_1.Contract(config_1.config[opts.environmentId].contracts.OperatorFactory, network_contracts_1.OperatorFactoryABI, opts.deployer);
    const contractAddress = await operatorFactory.operators(await opts.deployer.getAddress());
    if (contractAddress !== ethers_1.ZeroAddress) {
        throw new Error('Operator already has a contract');
    }
    const operatorReceipt = await (await operatorFactory.deployOperator((0, utils_1.multiplyWeiAmount)(FRACTION_MAX, ((opts.operatorsCutPercentage ?? 0) / 100)), opts.operatorTokenName ?? `OperatorToken-${Date.now()}`, opts.metadata ?? '', [
        config_1.config[opts.environmentId].contracts.OperatorDefaultDelegationPolicy,
        config_1.config[opts.environmentId].contracts.OperatorDefaultExchangeRatePolicy,
        config_1.config[opts.environmentId].contracts.OperatorDefaultUndelegationPolicy,
    ], [
        0,
        0,
        0
    ])).wait();
    const newSponsorshipEvent = operatorReceipt.logs.find((l) => l.fragment?.name === 'NewOperator');
    const newOperatorAddress = newSponsorshipEvent.args.operatorContractAddress;
    const newOperator = new ethers_1.Contract(newOperatorAddress, network_contracts_1.OperatorABI, opts.deployer);
    logger.debug('Deployed OperatorContract', { address: newOperatorAddress });
    return newOperator;
}
async function deploySponsorshipContract(opts) {
    logger.debug('Deploying SponsorshipContract');
    const sponsorshipFactory = new ethers_1.Contract(config_1.config[opts.environmentId].contracts.SponsorshipFactory, network_contracts_1.SponsorshipFactoryABI, opts.deployer);
    const policies = [{
            contractAddress: config_1.config[opts.environmentId].contracts.SponsorshipStakeWeightedAllocationPolicy,
            param: opts.earningsPerSecond
        }, {
            contractAddress: config_1.config[opts.environmentId].contracts.SponsorshipDefaultLeavePolicy,
            param: opts.minStakeDuration ?? 0,
        }, {
            contractAddress: config_1.config[opts.environmentId].contracts.SponsorshipVoteKickPolicy,
            param: 0
        }];
    if (opts.maxOperatorCount !== undefined) {
        policies.push({
            contractAddress: config_1.config[opts.environmentId].contracts.SponsorshipMaxOperatorsJoinPolicy,
            param: opts.maxOperatorCount
        });
    }
    const sponsorshipDeployTx = await sponsorshipFactory.deploySponsorship((opts.minOperatorCount ?? 1).toString(), opts.streamId, opts.metadata ?? '{}', policies.map((p) => p.contractAddress), policies.map((p) => p.param));
    const sponsorshipDeployReceipt = await sponsorshipDeployTx.wait();
    const newSponsorshipEvent = sponsorshipDeployReceipt.logs.find((l) => l.fragment?.name === 'NewSponsorship');
    const newSponsorshipAddress = newSponsorshipEvent.args.sponsorshipContract;
    const newSponsorship = new ethers_1.Contract(newSponsorshipAddress, network_contracts_1.SponsorshipABI, opts.deployer);
    logger.debug('Deployed SponsorshipContract', { address: newSponsorshipAddress });
    return newSponsorship;
}
const delegate = async (delegator, operatorContractAddress, amount) => {
    logger.debug('Delegate', { amount: amount.toString() });
    const tokenAddress = await (0, exports.getOperatorContract)(operatorContractAddress).connect(delegator.provider).token();
    await (0, exports.transferTokens)(delegator, operatorContractAddress, amount, tokenAddress);
};
exports.delegate = delegate;
const undelegate = async (delegator, operatorContractAddress, amount) => {
    logger.debug('Undelegate', { amount: amount.toString() });
    await (await (0, exports.getOperatorContract)(operatorContractAddress).connect(delegator).undelegate(amount)).wait();
};
exports.undelegate = undelegate;
const stake = async (staker, operatorContractAddress, sponsorshipContractAddress, amount) => {
    logger.debug('Stake', { amount: amount.toString() });
    const contract = (0, exports.getOperatorContract)(operatorContractAddress).connect(staker);
    await (await contract.stake(sponsorshipContractAddress, amount)).wait();
};
exports.stake = stake;
const unstake = async (staker, operatorContractAddress, sponsorshipContractAddress) => {
    logger.debug('Unstake');
    const contract = (0, exports.getOperatorContract)(operatorContractAddress).connect(staker);
    await (await contract.unstake(sponsorshipContractAddress)).wait();
};
exports.unstake = unstake;
const sponsor = async (sponsorer, sponsorshipContractAddress, amount) => {
    logger.debug('Sponsor', { amount: amount.toString() });
    const tokenAddress = await getSponsorshipContract(sponsorshipContractAddress).connect(sponsorer.provider).token();
    await (0, exports.transferTokens)(sponsorer, sponsorshipContractAddress, amount, tokenAddress);
};
exports.sponsor = sponsor;
const transferTokens = async (from, to, amount, tokenAddress) => {
    const token = new ethers_1.Contract(tokenAddress, network_contracts_1.DATAv2ABI);
    const tx = await token.connect(from).transferAndCall(to, amount, '0x');
    await tx.wait();
};
exports.transferTokens = transferTokens;
const getOperatorContract = (operatorAddress) => {
    return new ethers_1.Contract(operatorAddress, network_contracts_1.OperatorABI);
};
exports.getOperatorContract = getOperatorContract;
const getSponsorshipContract = (sponsorshipAddress) => {
    return new ethers_1.Contract(sponsorshipAddress, network_contracts_1.SponsorshipABI);
};
//# sourceMappingURL=operatorContractUtils.js.map