"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.validatePlaceOrderMessage = validatePlaceOrderMessage;
exports.validateCancelOrderMessage = validateCancelOrderMessage;
exports.validateBatchCancelOrderMessage = validateBatchCancelOrderMessage;
exports.validateTransferMessage = validateTransferMessage;
exports.verifyOrderFlags = verifyOrderFlags;
exports.isStatefulOrder = isStatefulOrder;
exports.isValidAddress = isValidAddress;
const bech32_1 = require("bech32");
const long_1 = __importDefault(require("long"));
const constants_1 = require("../clients/constants");
const types_1 = require("../clients/types");
const errors_1 = require("./errors");
/**
 * @describe validatePlaceOrderMessage validates that an order to place has fields that would be
 *  valid on-chain.
 */
function validatePlaceOrderMessage(subaccountNumber, order) {
    if (!verifyNumberIsUint32(order.clientId)) {
        return new errors_1.UserError(`clientId: ${order.clientId} is not a valid uint32`);
    }
    if (order.quantums.lessThanOrEqual(long_1.default.ZERO)) {
        return new errors_1.UserError(`quantums: ${order.quantums} cannot be <= 0`);
    }
    if (order.subticks.lessThanOrEqual(long_1.default.ZERO)) {
        return new errors_1.UserError(`subticks: ${order.subticks} cannot be <= 0`);
    }
    if (!verifySubaccountNumber(subaccountNumber)) {
        return new errors_1.UserError(`subaccountNumber: ${subaccountNumber} cannot be < 0 or > ${constants_1.MAX_SUBACCOUNT_NUMBER}`);
    }
    if (!isStatefulOrder(order.orderFlags) && !verifyGoodTilBlock(order.goodTilBlock)) {
        return new errors_1.UserError(`goodTilBlock: ${order.goodTilBlock} is not a valid uint32 or is 0`);
    }
    if (isStatefulOrder(order.orderFlags) && !verifyGoodTilBlockTime(order.goodTilBlockTime)) {
        return new errors_1.UserError(`goodTilBlockTime: ${order.goodTilBlockTime} is not a valid uint32 or is 0`);
    }
    return undefined;
}
/**
 * @describe validateCancelOrderMessage validates that an order to cancel has fields that would be
 *  valid on-chain.
 */
function validateCancelOrderMessage(subaccountNumber, order) {
    if (!verifyNumberIsUint32(order.clientId)) {
        return new errors_1.UserError(`clientId: ${order.clientId} is not a valid uint32`);
    }
    if (!isStatefulOrder(order.orderFlags) && !verifyGoodTilBlock(order.goodTilBlock)) {
        return new errors_1.UserError(`goodTilBlock: ${order.goodTilBlock} is not a valid uint32 or is 0`);
    }
    if (!isStatefulOrder(order.orderFlags) && order.goodTilBlockTime !== undefined) {
        return new errors_1.UserError(`goodTilBlockTime is ${order.goodTilBlockTime}, but should not be set for non-stateful orders`);
    }
    if (isStatefulOrder(order.orderFlags) && !verifyGoodTilBlockTime(order.goodTilBlockTime)) {
        return new errors_1.UserError(`goodTilBlockTime: ${order.goodTilBlockTime} is not a valid uint32 or is 0`);
    }
    if (isStatefulOrder(order.orderFlags) && order.goodTilBlock !== undefined) {
        return new errors_1.UserError(`goodTilBlock is ${order.goodTilBlock}, but should not be set for stateful orders`);
    }
    if (!verifySubaccountNumber(subaccountNumber)) {
        return new errors_1.UserError(`subaccountNumber: ${subaccountNumber} cannot be < 0 or > ${constants_1.MAX_SUBACCOUNT_NUMBER}`);
    }
    return undefined;
}
/**
 * @describe validateBatchCancelOrderMessage validates that orders to batch cancel have fields that would be
 *  valid on-chain.
 */
function validateBatchCancelOrderMessage(subaccountNumber, orders) {
    for (const orderBatch of orders.shortTermOrders) {
        for (const clientId of orderBatch.clientIds) {
            if (!verifyNumberIsUint32(clientId)) {
                return new errors_1.UserError(`clientId: ${clientId} is not a valid uint32`);
            }
        }
    }
    if (!verifyGoodTilBlock(orders.goodTilBlock)) {
        return new errors_1.UserError(`goodTilBlock: ${orders.goodTilBlock} is not a valid uint32 or is 0`);
    }
    if (!verifySubaccountNumber(subaccountNumber)) {
        return new errors_1.UserError(`subaccountNumber: ${subaccountNumber} cannot be < 0 or > ${constants_1.MAX_SUBACCOUNT_NUMBER}`);
    }
    return undefined;
}
/**
 * @describe validateTransferMessage validates that a transfer to place has fields that would be
 *  valid on-chain.
 */
function validateTransferMessage(transfer) {
    if (!verifySubaccountNumber(transfer.sender.number || 0)) {
        return new errors_1.UserError(`senderSubaccountNumber: ${transfer.sender.number || 0} cannot be < 0 or > ${constants_1.MAX_SUBACCOUNT_NUMBER}`);
    }
    if (!verifySubaccountNumber(transfer.recipient.number || 0)) {
        return new errors_1.UserError(`recipientSubaccountNumber: ${transfer.recipient.number || 0} cannot be < 0 or > ${constants_1.MAX_SUBACCOUNT_NUMBER}`);
    }
    if (transfer.assetId !== 0) {
        return new errors_1.UserError(`asset id: ${transfer.assetId} not supported`);
    }
    if (transfer.amount.lessThanOrEqual(long_1.default.ZERO)) {
        return new errors_1.UserError(`amount: ${transfer.amount} cannot be <= 0`);
    }
    const addressError = verifyIsBech32(transfer.recipient.owner);
    if (addressError !== undefined) {
        return new errors_1.UserError(addressError.toString());
    }
    return undefined;
}
function verifyGoodTilBlock(goodTilBlock) {
    if (goodTilBlock === undefined) {
        return false;
    }
    return verifyNumberIsUint32(goodTilBlock) && goodTilBlock > 0;
}
function verifyGoodTilBlockTime(goodTilBlockTime) {
    if (goodTilBlockTime === undefined) {
        return false;
    }
    return verifyNumberIsUint32(goodTilBlockTime) && goodTilBlockTime > 0;
}
function verifySubaccountNumber(subaccountNumber) {
    return subaccountNumber >= 0 && subaccountNumber <= constants_1.MAX_SUBACCOUNT_NUMBER;
}
function verifyNumberIsUint32(num) {
    return num >= 0 && num <= constants_1.MAX_UINT_32;
}
function verifyOrderFlags(orderFlags) {
    return (orderFlags === types_1.OrderFlags.SHORT_TERM ||
        orderFlags === types_1.OrderFlags.LONG_TERM ||
        orderFlags === types_1.OrderFlags.CONDITIONAL);
}
function isStatefulOrder(orderFlags) {
    return orderFlags === types_1.OrderFlags.LONG_TERM || orderFlags === types_1.OrderFlags.CONDITIONAL;
}
function verifyIsBech32(address) {
    try {
        (0, bech32_1.decode)(address);
    }
    catch (error) {
        return error;
    }
    return undefined;
}
function isValidAddress(address) {
    // An address is valid if it starts with the BECH32 prefix and is Bech32 format.
    return address.startsWith(constants_1.BECH32_PREFIX + '1') && verifyIsBech32(address) === undefined;
}
//# sourceMappingURL=data:application/json;base64, 