"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.signMetaTx = signMetaTx;
exports.signVoucherMetaTx = signVoucherMetaTx;
exports.signBiconomyVoucherMetaTx = signBiconomyVoucherMetaTx;
exports.relayBiconomyMetaTransaction = relayBiconomyMetaTransaction;
exports.signMetaTxCreateSeller = signMetaTxCreateSeller;
exports.signMetaTxUpdateSeller = signMetaTxUpdateSeller;
exports.signMetaTxOptInToSellerUpdate = signMetaTxOptInToSellerUpdate;
exports.signMetaTxCreateOffer = signMetaTxCreateOffer;
exports.signMetaTxCreateOfferBatch = signMetaTxCreateOfferBatch;
exports.signMetaTxVoidOffer = signMetaTxVoidOffer;
exports.signMetaTxVoidOfferBatch = signMetaTxVoidOfferBatch;
exports.signMetaTxExtendOffer = signMetaTxExtendOffer;
exports.signMetaTxExtendOfferBatch = signMetaTxExtendOfferBatch;
exports.signMetaTxCompleteExchangeBatch = signMetaTxCompleteExchangeBatch;
exports.signMetaTxExpireVoucher = signMetaTxExpireVoucher;
exports.signMetaTxRevokeVoucher = signMetaTxRevokeVoucher;
exports.signMetaTxCreateGroup = signMetaTxCreateGroup;
exports.signMetaTxReserveRange = signMetaTxReserveRange;
exports.signMetaTxPreMint = signMetaTxPreMint;
exports.signMetaTxSetApprovalForAll = signMetaTxSetApprovalForAll;
exports.signMetaTxSetApprovalForAllToContract = signMetaTxSetApprovalForAllToContract;
exports.signMetaTxCallExternalContract = signMetaTxCallExternalContract;
exports.signMetaTxCreateOfferWithCondition = signMetaTxCreateOfferWithCondition;
exports.signMetaTxCommitToOffer = signMetaTxCommitToOffer;
exports.signMetaTxCommitToConditionalOffer = signMetaTxCommitToConditionalOffer;
exports.signMetaTxCommitToBuyerOffer = signMetaTxCommitToBuyerOffer;
exports.signMetaTxCreateOfferAndCommit = signMetaTxCreateOfferAndCommit;
exports.signMetaTxCommitToOfferAndRedeemVoucher = signMetaTxCommitToOfferAndRedeemVoucher;
exports.signMetaTxCommitToConditionalOfferAndRedeemVoucher = signMetaTxCommitToConditionalOfferAndRedeemVoucher;
exports.signMetaTxCreateOfferCommitAndRedeem = signMetaTxCreateOfferCommitAndRedeem;
exports.signMetaTxCancelVoucher = signMetaTxCancelVoucher;
exports.signMetaTxRedeemVoucher = signMetaTxRedeemVoucher;
exports.signMetaTxCompleteExchange = signMetaTxCompleteExchange;
exports.signMetaTxRetractDispute = signMetaTxRetractDispute;
exports.signMetaTxEscalateDispute = signMetaTxEscalateDispute;
exports.signMetaTxRaiseDispute = signMetaTxRaiseDispute;
exports.signMetaTxResolveDispute = signMetaTxResolveDispute;
exports.signMetaTxExtendDisputeTimeout = signMetaTxExtendDisputeTimeout;
exports.signMetaTxWithdrawFunds = signMetaTxWithdrawFunds;
exports.signMetaTxDepositFunds = signMetaTxDepositFunds;
exports.relayMetaTransaction = relayMetaTransaction;
exports.executeMetaTransaction = executeMetaTransaction;
exports.executeMetaTransactionWithTokenTransferAuthorization = executeMetaTransactionWithTokenTransferAuthorization;
exports.getResubmitted = getResubmitted;
const common_1 = require("@bosonprotocol/common");
const storage_1 = require("../offers/storage");
const bignumber_1 = require("@ethersproject/bignumber");
const bytes_1 = require("@ethersproject/bytes");
const interface_1 = require("../accounts/interface");
const interface_2 = require("../exchanges/interface");
const interface_3 = require("../offers/interface");
const signature_1 = require("../utils/signature");
const biconomy_1 = require("./biconomy");
const interface_4 = require("./interface");
const address_1 = require("@ethersproject/address");
const constants_1 = require("@ethersproject/constants");
const interface_5 = require("../funds/interface");
const interface_6 = require("../disputes/interface");
const interface_7 = require("../groups/interface");
const interface_8 = require("../orchestration/interface");
const interface_9 = require("../voucher/interface");
const keccak256_1 = require("@ethersproject/keccak256");
const hash_1 = require("@ethersproject/hash");
const abi_1 = require("@ethersproject/abi");
const handler_1 = require("../erc20/handler");
const handler_2 = require("../forwarder/handler");
const handler_3 = require("../voucher/handler");
const handler_4 = require("../accounts/handler");
const storeMetadataItems_1 = require("../metadata/storeMetadataItems");
// Implementation
function signMetaTx(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const metaTransactionType = [
            { name: "nonce", type: "uint256" },
            { name: "from", type: "address" },
            { name: "contractAddress", type: "address" },
            { name: "functionName", type: "string" },
            { name: "functionSignature", type: "bytes" }
        ];
        const customSignatureType = {
            MetaTransaction: metaTransactionType
        };
        const signerAddress = yield args.web3Lib.getSignerAddress();
        const message = {
            nonce: args.nonce.toString(),
            from: signerAddress,
            contractAddress: args.metaTxHandlerAddress,
            functionName: args.functionName,
            functionSignature: args.functionSignature
        };
        if (args.returnTypedDataToSign) {
            const structuredData = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { verifyingContractAddress: args.metaTxHandlerAddress, customSignatureType, primaryType: "MetaTransaction", message, returnTypedDataToSign: true }));
            return Object.assign(Object.assign({}, structuredData), { functionName: args.functionName, functionSignature: args.functionSignature });
        }
        const signature = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { verifyingContractAddress: args.metaTxHandlerAddress, customSignatureType, primaryType: "MetaTransaction", message, returnTypedDataToSign: false }));
        return Object.assign({ functionName: args.functionName, functionSignature: args.functionSignature }, signature);
    });
}
function signVoucherMetaTx(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const forwardType = [
            { name: "from", type: "address" },
            { name: "to", type: "address" },
            { name: "nonce", type: "uint256" },
            { name: "data", type: "bytes" }
        ];
        const customSignatureType = {
            EIP712Domain: [
                { name: "name", type: "string" },
                { name: "version", type: "string" },
                { name: "chainId", type: "uint256" },
                { name: "verifyingContract", type: "address" }
            ],
            ForwardRequest: forwardType
        };
        const signerAddress = yield args.web3Lib.getSignerAddress();
        const chainId = yield args.web3Lib.getChainId();
        const nonce = yield (0, handler_2.getNonce)({
            contractAddress: args.forwarderAddress,
            user: signerAddress,
            web3Lib: args.web3Lib,
            forwarderAbi: args.forwarderAbi
        });
        const message = {
            from: signerAddress,
            to: args.bosonVoucherAddress,
            nonce,
            data: args.functionSignature
        };
        const signature = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { verifyingContractAddress: args.forwarderAddress, customSignatureType, primaryType: "ForwardRequest", message, customDomainData: {
                name: "MockForwarder",
                version: "0.0.1",
                chainId,
                salt: undefined
            }, returnTypedDataToSign: false }));
        return Object.assign({ to: message.to, functionSignature: args.functionSignature, request: message }, signature);
    });
}
function signBiconomyVoucherMetaTx(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const customSignatureType = {
            EIP712Domain: [
                { name: "name", type: "string" },
                { name: "version", type: "string" },
                // { name: "chainId", type: "uint256" },
                // { name: "verifyingContract", type: "address" }
                { name: "verifyingContract", type: "address" },
                { name: "salt", type: "bytes32" }
            ],
            ERC20ForwardRequest: [
                { name: "from", type: "address" },
                { name: "to", type: "address" },
                { name: "token", type: "address" },
                { name: "txGas", type: "uint256" },
                { name: "tokenGasPrice", type: "uint256" },
                { name: "batchId", type: "uint256" },
                { name: "batchNonce", type: "uint256" },
                { name: "deadline", type: "uint256" },
                { name: "data", type: "bytes" }
            ]
        };
        const signerAddress = yield args.web3Lib.getSignerAddress();
        const chainId = yield args.web3Lib.getChainId();
        // Check which forwarder needs to be used for the contract
        const biconomyForwarderDomainDetails = yield new biconomy_1.Biconomy(args.relayerUrl).getForwarderDomainDetails({ chainId });
        const biconomyForwarderDomainData = yield new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
            try {
                for (const bFDD of Object.values(biconomyForwarderDomainDetails)) {
                    const ret = yield (0, handler_3.isTrustedForwarder)({
                        forwarder: bFDD.verifyingContract,
                        contractAddress: args.bosonVoucherAddress,
                        web3Lib: args.web3Lib
                    });
                    if (ret) {
                        resolve(bFDD);
                    }
                }
                resolve(undefined);
            }
            catch (e) {
                reject(e);
            }
        }));
        if (!biconomyForwarderDomainData) {
            throw `Unable to find the trusted forwarder for BosonVoucher contract ${args.bosonVoucherAddress}`;
        }
        const nonce = yield (0, handler_2.getNonce)({
            contractAddress: biconomyForwarderDomainData.verifyingContract,
            user: signerAddress,
            web3Lib: args.web3Lib,
            batchId: args.batchId,
            forwarderAbi: args.forwarderAbi
        });
        const message = {
            from: signerAddress,
            to: args.bosonVoucherAddress,
            token: "0x0000000000000000000000000000000000000000",
            txGas: args.txGas,
            tokenGasPrice: "0",
            batchId: args.batchId,
            batchNonce: nonce,
            deadline: Math.floor(Date.now() / 1000 + 3600),
            data: args.functionSignature
        };
        const signatureParams = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { chainId, verifyingContractAddress: biconomyForwarderDomainData.verifyingContract, customSignatureType, primaryType: "ERC20ForwardRequest", message, customDomainData: Object.assign({}, biconomyForwarderDomainData
            // chainId
            // salt: undefined
            ), returnTypedDataToSign: false }));
        const signature = signatureParams.signature;
        const getDomainSeparator = () => __awaiter(this, void 0, void 0, function* () {
            const domainData = biconomyForwarderDomainData;
            const domainSeparator = (0, keccak256_1.keccak256)(abi_1.defaultAbiCoder.encode(["bytes32", "bytes32", "bytes32", "address", "bytes32"], [
                (0, hash_1.id)("EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)"),
                (0, hash_1.id)(domainData.name),
                (0, hash_1.id)(domainData.version),
                domainData.verifyingContract,
                domainData.salt
            ]));
            return domainSeparator;
        });
        const domainSeparator = yield getDomainSeparator();
        // verify signature
        const signatureVerified = yield (0, handler_2.verifyEIP712)({
            request: message,
            contractAddress: biconomyForwarderDomainData.verifyingContract,
            web3Lib: args.web3Lib,
            domainSeparator,
            forwarderAbi: args.forwarderAbi,
            signature
        });
        if (!signatureVerified) {
            throw `Signature is not verified`;
        }
        return Object.assign(Object.assign({ to: message.to, domainSeparator, request: message }, signatureParams), { signature, functionSignature: args.functionSignature });
    });
}
function relayBiconomyMetaTransaction(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const { chainId, contractAddress, metaTx } = args;
        const biconomy = new biconomy_1.Biconomy(metaTx.config.relayerUrl, metaTx.config.apiKey, metaTx.config.apiId);
        const relayTxResponse = yield biconomy.relayTransaction({
            to: contractAddress,
            params: [
                metaTx.params.request,
                metaTx.params.domainSeparator,
                metaTx.params.signature
            ],
            from: metaTx.params.userAddress,
            signatureType: "EIP712_SIGN"
        });
        return {
            wait: () => __awaiter(this, void 0, void 0, function* () {
                const waitResponse = yield biconomy.wait({
                    networkId: chainId,
                    transactionHash: relayTxResponse.txHash
                });
                const txHash = waitResponse.data.newHash;
                const txReceipt = yield args.web3LibAdapter.getTransactionReceipt(txHash);
                return {
                    to: (txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.to) || contractAddress,
                    from: (txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.from) || metaTx.params.userAddress,
                    transactionHash: txHash,
                    logs: (txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.logs) || [],
                    effectiveGasPrice: bignumber_1.BigNumber.from(waitResponse.data.newGasPrice),
                    blockNumber: txReceipt.blockNumber,
                    gasUsed: txReceipt.gasUsed
                };
            }),
            hash: relayTxResponse.txHash
        };
    });
}
// Implementation
function signMetaTxCreateSeller(args) {
    return __awaiter(this, void 0, void 0, function* () {
        yield Promise.all([args.createSellerArgs.contractUri, args.createSellerArgs.metadataUri].map((metadataUri) => (0, storage_1.storeMetadataOnTheGraph)({
            metadataUriOrHash: metadataUri,
            metadataStorage: args.metadataStorage,
            theGraphStorage: args.theGraphStorage
        })));
        const collectionSalt = yield (0, handler_4.findCollectionSalt)(Object.assign({ sellerToCreate: args.createSellerArgs, contractAddress: args.metaTxHandlerAddress }, args));
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "createSeller((uint256,address,address,address,address,bool,string),(uint256,uint8),(string,uint256,bytes32))", functionSignature: (0, interface_1.encodeCreateSeller)(args.createSellerArgs, collectionSalt) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxUpdateSeller(args) {
    return __awaiter(this, void 0, void 0, function* () {
        yield (0, storage_1.storeMetadataOnTheGraph)({
            metadataUriOrHash: args.updateSellerArgs.metadataUri,
            metadataStorage: args.metadataStorage,
            theGraphStorage: args.theGraphStorage
        });
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "updateSeller((uint256,address,address,address,address,bool,string),(uint256,uint8))", functionSignature: (0, interface_1.encodeUpdateSeller)(args.updateSellerArgs) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxOptInToSellerUpdate(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "optInToSellerUpdate(uint256,uint8[])", functionSignature: (0, interface_1.encodeOptInToSellerUpdate)(args.optInToSellerUpdateArgs) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxCreateOffer(args) {
    return __awaiter(this, void 0, void 0, function* () {
        common_1.utils.validation.createOfferArgsSchema.validateSync(args.createOfferArgs, {
            abortEarly: false
        });
        yield (0, storage_1.storeMetadataOnTheGraph)({
            metadataUriOrHash: args.createOfferArgs.metadataUri,
            metadataStorage: args.metadataStorage,
            theGraphStorage: args.theGraphStorage
        });
        yield (0, storeMetadataItems_1.storeMetadataItems)(Object.assign(Object.assign({}, args), { createOffersArgs: [args.createOfferArgs] }));
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "createOffer((uint256,uint256,uint256,uint256,uint256,uint256,address,uint8,uint8,string,string,bool,uint256,(address[],uint256[])[],uint256),(uint256,uint256,uint256,uint256),(uint256,uint256,uint256),(uint256,address),uint256,uint256)", functionSignature: (0, interface_3.encodeCreateOffer)(args.createOfferArgs) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxCreateOfferBatch(args) {
    return __awaiter(this, void 0, void 0, function* () {
        for (const offerToCreate of args.createOffersArgs) {
            common_1.utils.validation.createOfferArgsSchema.validateSync(offerToCreate, {
                abortEarly: false
            });
        }
        yield Promise.all(args.createOffersArgs.map((offerToCreate) => (0, storage_1.storeMetadataOnTheGraph)({
            metadataUriOrHash: offerToCreate.metadataUri,
            metadataStorage: args.metadataStorage,
            theGraphStorage: args.theGraphStorage
        })));
        yield (0, storeMetadataItems_1.storeMetadataItems)(args);
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "createOfferBatch((uint256,uint256,uint256,uint256,uint256,uint256,address,uint8,uint8,string,string,bool,uint256,(address[],uint256[])[],uint256)[],(uint256,uint256,uint256,uint256)[],(uint256,uint256,uint256)[],(uint256,address)[],uint256[],uint256[])", functionSignature: (0, interface_3.encodeCreateOfferBatch)(args.createOffersArgs) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxVoidOffer(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "voidOffer(uint256)", functionSignature: interface_3.bosonOfferHandlerIface.encodeFunctionData("voidOffer", [
                args.offerId
            ]) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxVoidOfferBatch(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "voidOfferBatch(uint256[])", functionSignature: interface_3.bosonOfferHandlerIface.encodeFunctionData("voidOfferBatch", [args.offerIds]) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxExtendOffer(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "extendOffer(uint256,uint256)", functionSignature: interface_3.bosonOfferHandlerIface.encodeFunctionData("extendOffer", [args.offerId, args.validUntil]) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxExtendOfferBatch(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "extendOfferBatch(uint256[],uint256)", functionSignature: interface_3.bosonOfferHandlerIface.encodeFunctionData("extendOfferBatch", [args.offerIds, args.validUntil]) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxCompleteExchangeBatch(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "completeExchangeBatch(uint256[])", functionSignature: interface_2.bosonExchangeHandlerIface.encodeFunctionData("completeExchangeBatch", [args.exchangeIds]) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxExpireVoucher(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "expireVoucher(uint256)", functionSignature: interface_2.bosonExchangeHandlerIface.encodeFunctionData("expireVoucher", [args.exchangeId]) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxRevokeVoucher(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "revokeVoucher(uint256)", functionSignature: interface_2.bosonExchangeHandlerIface.encodeFunctionData("revokeVoucher", [args.exchangeId]) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxCreateGroup(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "createGroup((uint256,uint256,uint256[]),(uint8,uint8,address,uint8,uint256,uint256,uint256,uint256))", functionSignature: (0, interface_7.encodeCreateGroup)(args.createGroupArgs) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxReserveRange(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "reserveRange(uint256,uint256,address)", functionSignature: (0, interface_3.encodeReserveRange)(args.offerId, args.length, args.to) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
function isLocal(chainId) {
    const localConfigs = common_1.envConfigs["local"];
    return localConfigs.some((localConfig) => localConfig.chainId === chainId);
}
function signMetaTxPreMint(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const functionSignature = (0, interface_9.encodePreMint)(args.offerId, args.amount);
        if (isLocal(args.chainId)) {
            return signVoucherMetaTx(Object.assign(Object.assign({}, args), { forwarderAddress: args.forwarderAddress, functionSignature, forwarderAbi: args.forwarderAbi }));
        }
        const txGas = 200000 + bignumber_1.BigNumber.from(args.amount).mul(2500).toNumber(); // ~(180000 + 2250*N) estimation on 2023/02/03
        return signBiconomyVoucherMetaTx(Object.assign(Object.assign({}, args), { functionSignature, forwarderAbi: args.forwarderAbi, batchId: args.batchId || "0", txGas }));
    });
}
function signMetaTxSetApprovalForAll(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const functionSignature = (0, interface_9.encodeSetApprovalForAll)(args.operator, args.approved);
        if (isLocal(args.chainId)) {
            return signVoucherMetaTx(Object.assign(Object.assign({}, args), { forwarderAddress: args.forwarderAddress, functionSignature, forwarderAbi: args.forwarderAbi }));
        }
        const txGas = 100000; // ~70000 estimation on 2023/02/03
        return signBiconomyVoucherMetaTx(Object.assign(Object.assign({}, args), { functionSignature, forwarderAbi: args.forwarderAbi, batchId: args.batchId || "0", txGas }));
    });
}
function signMetaTxSetApprovalForAllToContract(args_1) {
    return __awaiter(this, arguments, void 0, function* (args, overrides = {}) {
        const functionSignature = (0, interface_9.encodeSetApprovalForAllToContract)(args.operator, args.approved);
        if (isLocal(args.chainId)) {
            return signVoucherMetaTx(Object.assign(Object.assign({}, args), { forwarderAddress: args.forwarderAddress, functionSignature, forwarderAbi: args.forwarderAbi }));
        }
        const txGas = overrides.txGas || 100000; // TODO: estimate the gas needed
        return signBiconomyVoucherMetaTx(Object.assign(Object.assign({}, args), { functionSignature, forwarderAbi: args.forwarderAbi, batchId: args.batchId || "0", txGas }));
    });
}
function signMetaTxCallExternalContract(args_1) {
    return __awaiter(this, arguments, void 0, function* (args, overrides = {}) {
        const functionSignature = (0, interface_9.encodeCallExternalContract)(args.to, args.data);
        if (isLocal(args.chainId)) {
            return signVoucherMetaTx(Object.assign(Object.assign({}, args), { forwarderAddress: args.forwarderAddress, functionSignature, forwarderAbi: args.forwarderAbi }));
        }
        const txGas = overrides.txGas || 500000; // TODO: estimate the gas needed
        return signBiconomyVoucherMetaTx(Object.assign(Object.assign({}, args), { functionSignature, forwarderAbi: args.forwarderAbi, batchId: args.batchId || "0", txGas }));
    });
}
// Implementation
function signMetaTxCreateOfferWithCondition(args) {
    return __awaiter(this, void 0, void 0, function* () {
        common_1.utils.validation.createOfferArgsSchema.validateSync(args.offerToCreate, {
            abortEarly: false
        });
        yield (0, storage_1.storeMetadataOnTheGraph)({
            metadataUriOrHash: args.offerToCreate.metadataUri,
            metadataStorage: args.metadataStorage,
            theGraphStorage: args.theGraphStorage
        });
        yield (0, storeMetadataItems_1.storeMetadataItems)(Object.assign(Object.assign({}, args), { createOffersArgs: [args.offerToCreate] }));
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "createOfferWithCondition((uint256,uint256,uint256,uint256,uint256,uint256,address,uint8,uint8,string,string,bool,uint256,(address[],uint256[])[],uint256),(uint256,uint256,uint256,uint256),(uint256,uint256,uint256),(uint256,address),(uint8,uint8,address,uint8,uint256,uint256,uint256,uint256),uint256,uint256)", functionSignature: (0, interface_8.encodeCreateOfferWithCondition)(args.offerToCreate, args.condition) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxCommitToOffer(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const functionName = "commitToOffer(address,uint256)";
        const offerType = [
            { name: "buyer", type: "address" },
            { name: "offerId", type: "uint256" }
        ];
        const metaTransactionType = [
            { name: "nonce", type: "uint256" },
            { name: "from", type: "address" },
            { name: "contractAddress", type: "address" },
            { name: "functionName", type: "string" },
            { name: "offerDetails", type: "MetaTxOfferDetails" }
        ];
        const customSignatureType = {
            MetaTxCommitToOffer: metaTransactionType,
            MetaTxOfferDetails: offerType
        };
        const buyerAddress = yield args.web3Lib.getSignerAddress();
        const message = {
            nonce: args.nonce.toString(),
            from: buyerAddress,
            contractAddress: args.metaTxHandlerAddress,
            functionName,
            offerDetails: {
                buyer: buyerAddress,
                offerId: args.offerId.toString()
            }
        };
        const functionSignature = interface_2.bosonExchangeCommitHandlerIface.encodeFunctionData("commitToOffer", [buyerAddress, args.offerId]);
        if (args.returnTypedDataToSign) {
            const structuredData = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { verifyingContractAddress: args.metaTxHandlerAddress, customSignatureType, primaryType: "MetaTxCommitToOffer", message, returnTypedDataToSign: true }));
            return Object.assign(Object.assign({}, structuredData), { functionName, functionSignature });
        }
        const signatureParams = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { verifyingContractAddress: args.metaTxHandlerAddress, customSignatureType, primaryType: "MetaTxCommitToOffer", message, returnTypedDataToSign: false }));
        return Object.assign(Object.assign({}, signatureParams), { functionName,
            functionSignature });
    });
}
// Implementation
function signMetaTxCommitToConditionalOffer(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const functionName = "commitToConditionalOffer(address,uint256,uint256)";
        const offerType = [
            { name: "buyer", type: "address" },
            { name: "offerId", type: "uint256" },
            { name: "tokenId", type: "uint256" }
        ];
        const metaTransactionType = [
            { name: "nonce", type: "uint256" },
            { name: "from", type: "address" },
            { name: "contractAddress", type: "address" },
            { name: "functionName", type: "string" },
            { name: "offerDetails", type: "MetaTxConditionalOfferDetails" }
        ];
        const customSignatureType = {
            MetaTxCommitToConditionalOffer: metaTransactionType,
            MetaTxConditionalOfferDetails: offerType
        };
        const buyerAddress = yield args.web3Lib.getSignerAddress();
        const message = {
            nonce: args.nonce.toString(),
            from: buyerAddress,
            contractAddress: args.metaTxHandlerAddress,
            functionName,
            offerDetails: {
                buyer: buyerAddress,
                offerId: args.offerId.toString(),
                tokenId: args.tokenId.toString()
            }
        };
        const functionSignature = interface_2.bosonExchangeCommitHandlerIface.encodeFunctionData("commitToConditionalOffer", [buyerAddress, args.offerId, args.tokenId]);
        if (args.returnTypedDataToSign) {
            const structuredData = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { verifyingContractAddress: args.metaTxHandlerAddress, customSignatureType, primaryType: "MetaTxCommitToConditionalOffer", message, returnTypedDataToSign: true }));
            return Object.assign(Object.assign({}, structuredData), { functionName, functionSignature });
        }
        const signatureParams = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { verifyingContractAddress: args.metaTxHandlerAddress, customSignatureType, primaryType: "MetaTxCommitToConditionalOffer", message, returnTypedDataToSign: false }));
        return Object.assign(Object.assign({}, signatureParams), { functionName,
            functionSignature });
    });
}
// Implementation
function signMetaTxCommitToBuyerOffer(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const functionName = "commitToBuyerOffer(uint256,(uint256,(address[],uint256[]),address))";
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName, functionSignature: (0, interface_2.encodeCommitToBuyerOffer)(args.offerId, args.sellerParams) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxCreateOfferAndCommit(args) {
    return __awaiter(this, void 0, void 0, function* () {
        common_1.utils.validation.createOfferAndCommitArgsSchema.validateSync(args.createOfferAndCommitArgs, { abortEarly: false });
        yield (0, storage_1.storeMetadataOnTheGraph)({
            metadataUriOrHash: args.createOfferAndCommitArgs.metadataUri,
            metadataStorage: args.metadataStorage,
            theGraphStorage: args.theGraphStorage
        });
        yield (0, storeMetadataItems_1.storeMetadataItems)(Object.assign(Object.assign({}, args), { createOffersArgs: [args.createOfferAndCommitArgs] }));
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "createOfferAndCommit(((uint256,uint256,uint256,uint256,uint256,uint256,address,uint8,uint8,string,string,bool,uint256,(address[],uint256[])[],uint256),(uint256,uint256,uint256,uint256),(uint256,uint256,uint256),(uint256,address),(uint8,uint8,address,uint8,uint256,uint256,uint256,uint256),uint256,uint256,bool),address,address,bytes,uint256,(uint256,(address[],uint256[]),address))", functionSignature: (0, interface_2.encodeCreateOfferAndCommit)(args.createOfferAndCommitArgs) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxCommitToOfferAndRedeemVoucher(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "commitToOfferAndRedeemVoucher(uint256)", functionSignature: (0, interface_8.encodeCommitToOfferAndRedeemVoucher)(args.offerId) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxCommitToConditionalOfferAndRedeemVoucher(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "commitToConditionalOfferAndRedeemVoucher(uint256,uint256)", functionSignature: (0, interface_8.encodeCommitToConditionalOfferAndRedeemVoucher)(args.offerId, args.tokenId) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxCreateOfferCommitAndRedeem(args) {
    return __awaiter(this, void 0, void 0, function* () {
        common_1.utils.validation.createOfferAndCommitArgsSchema.validateSync(args.createOfferAndCommitArgs, { abortEarly: false });
        yield (0, storage_1.storeMetadataOnTheGraph)({
            metadataUriOrHash: args.createOfferAndCommitArgs.metadataUri,
            metadataStorage: args.metadataStorage,
            theGraphStorage: args.theGraphStorage
        });
        yield (0, storeMetadataItems_1.storeMetadataItems)(Object.assign(Object.assign({}, args), { createOffersArgs: [args.createOfferAndCommitArgs] }));
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "createOfferCommitAndRedeem(((uint256,uint256,uint256,uint256,uint256,uint256,address,uint8,uint8,string,string,bool,uint256,(address[],uint256[])[],uint256),(uint256,uint256,uint256,uint256),(uint256,uint256,uint256),(uint256,address),(uint8,uint8,address,uint8,uint256,uint256,uint256,uint256),uint256,uint256,bool),address,bytes,uint256)", functionSignature: (0, interface_8.encodeCreateOfferCommitAndRedeem)(args.createOfferAndCommitArgs) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxCancelVoucher(args) {
    return __awaiter(this, void 0, void 0, function* () {
        return makeExchangeMetaTxSigner("cancelVoucher(uint256)")(args);
    });
}
// Implementation
function signMetaTxRedeemVoucher(args) {
    return __awaiter(this, void 0, void 0, function* () {
        return makeExchangeMetaTxSigner("redeemVoucher(uint256)")(args);
    });
}
// Implementation
function signMetaTxCompleteExchange(args) {
    return __awaiter(this, void 0, void 0, function* () {
        return makeExchangeMetaTxSigner("completeExchange(uint256)")(args);
    });
}
// Implementation
function signMetaTxRetractDispute(args) {
    return __awaiter(this, void 0, void 0, function* () {
        return makeExchangeMetaTxSigner("retractDispute(uint256)", interface_6.bosonDisputeHandlerIface)(args);
    });
}
// Implementation
function signMetaTxEscalateDispute(args) {
    return __awaiter(this, void 0, void 0, function* () {
        return makeExchangeMetaTxSigner("escalateDispute(uint256)", interface_6.bosonDisputeHandlerIface)(args);
    });
}
// Implementation
function signMetaTxRaiseDispute(args) {
    return __awaiter(this, void 0, void 0, function* () {
        return makeExchangeMetaTxSigner("raiseDispute(uint256)", interface_6.bosonDisputeHandlerIface)(args);
    });
}
// Implementation
function signMetaTxResolveDispute(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const functionName = "resolveDispute(uint256,uint256,bytes)";
        const counterpartySig = typeof args.counterpartySig === "string"
            ? args.counterpartySig
            : (0, signature_1.rebuildSignature)(args.counterpartySig);
        const disputeResolutionType = [
            { name: "exchangeId", type: "uint256" },
            { name: "buyerPercentBasisPoints", type: "uint256" },
            { name: "signature", type: "bytes" }
        ];
        const metaTransactionType = [
            { name: "nonce", type: "uint256" },
            { name: "from", type: "address" },
            { name: "contractAddress", type: "address" },
            { name: "functionName", type: "string" },
            { name: "disputeResolutionDetails", type: "MetaTxDisputeResolutionDetails" }
        ];
        const customSignatureType = {
            MetaTxDisputeResolution: metaTransactionType,
            MetaTxDisputeResolutionDetails: disputeResolutionType
        };
        const message = {
            nonce: args.nonce.toString(),
            from: yield args.web3Lib.getSignerAddress(),
            contractAddress: args.metaTxHandlerAddress,
            functionName,
            disputeResolutionDetails: {
                exchangeId: args.exchangeId.toString(),
                buyerPercentBasisPoints: args.buyerPercent.toString(),
                signature: counterpartySig
            }
        };
        const functionSignature = interface_6.bosonDisputeHandlerIface.encodeFunctionData(
        // remove params in brackets from string
        functionName.replace(/\(([^)]*)\)[^(]*$/, ""), [args.exchangeId, args.buyerPercent, counterpartySig]);
        if (args.returnTypedDataToSign) {
            const structuredData = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { verifyingContractAddress: args.metaTxHandlerAddress, customSignatureType, primaryType: "MetaTxDisputeResolution", message, returnTypedDataToSign: true }));
            return Object.assign(Object.assign({}, structuredData), { functionName, functionSignature });
        }
        const signatureParams = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { verifyingContractAddress: args.metaTxHandlerAddress, customSignatureType, primaryType: "MetaTxDisputeResolution", message, returnTypedDataToSign: false }));
        return Object.assign(Object.assign({}, signatureParams), { functionName,
            functionSignature });
    });
}
// Implementation
function signMetaTxExtendDisputeTimeout(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "extendDisputeTimeout(uint256,uint256)", functionSignature: interface_6.bosonDisputeHandlerIface.encodeFunctionData("extendDisputeTimeout", [args.exchangeId, args.newTimeout]) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
// Implementation
function signMetaTxWithdrawFunds(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const functionName = "withdrawFunds(uint256,address[],uint256[])";
        const fundType = [
            { name: "entityId", type: "uint256" },
            { name: "tokenList", type: "address[]" },
            { name: "tokenAmounts", type: "uint256[]" }
        ];
        const metaTransactionType = [
            { name: "nonce", type: "uint256" },
            { name: "from", type: "address" },
            { name: "contractAddress", type: "address" },
            { name: "functionName", type: "string" },
            { name: "fundDetails", type: "MetaTxFundDetails" }
        ];
        const customSignatureType = {
            MetaTxFund: metaTransactionType,
            MetaTxFundDetails: fundType
        };
        const message = {
            nonce: args.nonce.toString(),
            from: yield args.web3Lib.getSignerAddress(),
            contractAddress: args.metaTxHandlerAddress,
            functionName,
            fundDetails: {
                entityId: args.entityId.toString(),
                tokenList: args.tokenList,
                tokenAmounts: args.tokenAmounts.map((bn) => bn.toString())
            }
        };
        const functionSignature = (0, interface_5.encodeWithdrawFunds)(args.entityId, args.tokenList, args.tokenAmounts);
        if (args.returnTypedDataToSign) {
            const structuredData = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { verifyingContractAddress: args.metaTxHandlerAddress, customSignatureType, primaryType: "MetaTxFund", message, returnTypedDataToSign: true }));
            return Object.assign(Object.assign({}, structuredData), { functionName, functionSignature });
        }
        const signatureParams = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { verifyingContractAddress: args.metaTxHandlerAddress, customSignatureType, primaryType: "MetaTxFund", message, returnTypedDataToSign: false }));
        return Object.assign(Object.assign({}, signatureParams), { functionName,
            functionSignature });
    });
}
// Implementation
function signMetaTxDepositFunds(args) {
    return __awaiter(this, void 0, void 0, function* () {
        if (!(0, address_1.isAddress)(args.fundsTokenAddress)) {
            throw new Error(`Invalid fundsTokenAddress: ${args.fundsTokenAddress}`);
        }
        if (args.fundsTokenAddress === constants_1.AddressZero) {
            throw new Error(`Meta transaction can't be used to deposit native currency`);
        }
        const signMetaTxArgs = Object.assign(Object.assign({}, args), { functionName: "depositFunds(uint256,address,uint256)", functionSignature: (0, interface_5.encodeDepositFunds)(args.entityId, args.fundsTokenAddress, args.fundsAmount) });
        if (args.returnTypedDataToSign) {
            return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: true }));
        }
        return signMetaTx(Object.assign(Object.assign({}, signMetaTxArgs), { returnTypedDataToSign: false }));
    });
}
function makeExchangeMetaTxSigner(functionName, handlerIface = interface_2.bosonExchangeHandlerIface) {
    return function signExchangeMetaTx(args) {
        return __awaiter(this, void 0, void 0, function* () {
            const exchangeType = [{ name: "exchangeId", type: "uint256" }];
            const metaTransactionType = [
                { name: "nonce", type: "uint256" },
                { name: "from", type: "address" },
                { name: "contractAddress", type: "address" },
                { name: "functionName", type: "string" },
                { name: "exchangeDetails", type: "MetaTxExchangeDetails" }
            ];
            const customSignatureType = {
                MetaTxExchange: metaTransactionType,
                MetaTxExchangeDetails: exchangeType
            };
            const buyerAddress = yield args.web3Lib.getSignerAddress();
            const message = {
                nonce: args.nonce.toString(),
                from: buyerAddress,
                contractAddress: args.metaTxHandlerAddress,
                functionName,
                exchangeDetails: {
                    exchangeId: args.exchangeId.toString()
                }
            };
            const functionSignature = handlerIface.encodeFunctionData(
            // remove params in brackets from string
            functionName.replace(/\(([^)]*)\)[^(]*$/, ""), [args.exchangeId]);
            if (args.returnTypedDataToSign) {
                const structuredData = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { verifyingContractAddress: args.metaTxHandlerAddress, customSignatureType, primaryType: "MetaTxExchange", message, returnTypedDataToSign: true }));
                return Object.assign(Object.assign({}, structuredData), { functionName, functionSignature });
            }
            const signatureParams = yield (0, signature_1.prepareDataSignatureParameters)(Object.assign(Object.assign({}, args), { verifyingContractAddress: args.metaTxHandlerAddress, customSignatureType, primaryType: "MetaTxExchange", message, returnTypedDataToSign: false }));
            return Object.assign(Object.assign({}, signatureParams), { functionName,
                functionSignature });
        });
    };
}
function relayMetaTransaction(args) {
    return __awaiter(this, void 0, void 0, function* () {
        var _a;
        const { chainId, contractAddress, metaTx } = args;
        const biconomy = new biconomy_1.Biconomy(metaTx.config.relayerUrl, metaTx.config.apiKey, metaTx.config.apiId);
        const baseParams = [
            metaTx.params.userAddress,
            metaTx.params.functionName,
            metaTx.params.functionSignature,
            metaTx.params.nonce,
            (0, signature_1.rebuildSignature)({
                r: metaTx.params.sigR.toString(),
                s: metaTx.params.sigS.toString(),
                v: Number(metaTx.params.sigV)
            })
        ];
        const params = ((_a = metaTx.params.transferAuthorizations) === null || _a === void 0 ? void 0 : _a.length)
            ? [
                ...baseParams,
                metaTx.params.transferAuthorizations.map(handler_1.encodeTransferAuthorizationEntry)
            ]
            : baseParams;
        const relayTxResponse = yield biconomy.relayTransaction({
            to: contractAddress,
            params,
            from: metaTx.params.userAddress
        });
        return {
            wait: () => __awaiter(this, void 0, void 0, function* () {
                const waitResponse = yield biconomy.wait({
                    networkId: chainId,
                    transactionHash: relayTxResponse.txHash
                });
                const txHash = waitResponse.data.newHash;
                const txReceipt = yield args.web3LibAdapter.getTransactionReceipt(txHash);
                return {
                    to: (txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.to) || contractAddress,
                    from: (txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.from) || metaTx.params.userAddress,
                    transactionHash: txHash,
                    logs: (txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.logs) || [],
                    effectiveGasPrice: bignumber_1.BigNumber.from(waitResponse.data.newGasPrice),
                    blockNumber: txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.blockNumber,
                    gasUsed: txReceipt.gasUsed
                };
            }),
            hash: relayTxResponse.txHash
        };
    });
}
// Implementation
function executeMetaTransaction(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const data = interface_4.metaTransactionsHandlerIface.encodeFunctionData("executeMetaTransaction", [
            args.userAddress,
            args.functionName,
            args.functionSignature,
            args.nonce,
            (0, signature_1.rebuildSignature)({
                r: (0, bytes_1.hexlify)(args.sigR),
                s: (0, bytes_1.hexlify)(args.sigS),
                v: Number(args.sigV)
            })
        ]);
        const tx = { to: args.contractAddress, data };
        return args.returnTxInfo ? tx : args.web3Lib.sendTransaction(tx);
    });
}
// Implementation
function executeMetaTransactionWithTokenTransferAuthorization(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const data = interface_4.metaTransactionsHandlerIface.encodeFunctionData("executeMetaTransactionWithTokenTransferAuthorization", [
            args.userAddress,
            args.functionName,
            args.functionSignature,
            args.nonce,
            (0, signature_1.rebuildSignature)({
                r: (0, bytes_1.hexlify)(args.sigR),
                s: (0, bytes_1.hexlify)(args.sigS),
                v: Number(args.sigV)
            }),
            args.transferAuthorizations.map(handler_1.encodeTransferAuthorizationEntry)
        ]);
        const tx = { to: args.contractAddress, data };
        return args.returnTxInfo ? tx : args.web3Lib.sendTransaction(tx);
    });
}
function getResubmitted(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const { chainId, metaTx } = args;
        const biconomy = new biconomy_1.Biconomy(metaTx.config.relayerUrl, metaTx.config.apiKey, metaTx.config.apiId);
        const retriedHashesResponse = yield biconomy.getResubmitted({
            networkId: chainId,
            transactionHash: metaTx.originalHash
        });
        return retriedHashesResponse.data;
    });
}
//# sourceMappingURL=handler.js.map