Repository: ccxt/ccxt
File: ts/src/test/Exchange/base/test.sharedMethods.ts (TypeScript)

Code before:
                assert (typeAssertion, '"' + stringValue (key) + '" key is neither undefined, neither of expected type' + logText);
                if (deep) {
                    if (typeof value === 'object') {
                        assertStructure (exchange, skippedProperties, method, value, format[key], emptyAllowedFor, deep);
                    }
                }
            }
        }
    }
}

function assertTimestamp (exchange: Exchange, skippedProperties: object, method: string, entry: object, nowToCheck: any = undefined, keyNameOrIndex : string | number = 'timestamp') {
    const logText = logTemplate (exchange, method, entry);
    const skipValue = exchange.safeValue (skippedProperties, keyNameOrIndex);
    if (skipValue !== undefined) {
        return; // skipped
    }
    const isDateTimeObject = typeof keyNameOrIndex === 'string';
    if (isDateTimeObject) {
        assert ((keyNameOrIndex in entry), 'timestamp key "' + keyNameOrIndex + '" is missing from structure' + logText);
    } else {
        // if index was provided (mostly from fetchOHLCV) then we check if it exists, as mandatory
        assert (!(entry[keyNameOrIndex] === undefined), 'timestamp index ' + stringValue (keyNameOrIndex) + ' is undefined' + logText);
    }
    const ts = entry[keyNameOrIndex];
    if (ts !== undefined) {
        assert (typeof ts === 'number', 'timestamp is not numeric' + logText);
        assert (Number.isInteger (ts), 'timestamp should be an integer' + logText);
        const minTs = 1230940800000; // 03 Jan 2009 - first block
        const maxTs = 2147483648000; // 19 Jan 2038 - max int
        assert (ts > minTs, 'timestamp is impossible to be before ' + minTs.toString () + ' (03.01.2009)' + logText); // 03 Jan 2009 - first block
        assert (ts < maxTs, 'timestamp more than ' + maxTs.toString () + ' (19.01.2038)' + logText); // 19 Jan 2038 - int32 overflows // 7258118400000  -> Jan 1 2200
        if (nowToCheck !== undefined) {
            const maxMsOffset = 60000; // 1 min
            assert (ts < nowToCheck + maxMsOffset, 'returned item timestamp (' + exchange.iso8601 (ts) + ') is ahead of the current time (' + exchange.iso8601 (nowToCheck) + ')' + logText);
        }
    }
}

function assertTimestampAndDatetime (exchange: Exchange, skippedProperties: object, method: string, entry: object, nowToCheck: any = undefined, keyNameOrIndex : any = 'timestamp') {
    const logText = logTemplate (exchange, method, entry);
    const skipValue = exchange.safeValue (skippedProperties, keyNameOrIndex);
    if (skipValue !== undefined) {
        return;
    }
    assertTimestamp (exchange, skippedProperties, method, entry, nowToCheck, keyNameOrIndex);
    const isDateTimeObject = typeof keyNameOrIndex === 'string';
    // only in case if the entry is a dictionary, thus it must have 'timestamp' & 'datetime' string keys
    if (isDateTimeObject) {
        // we also test 'datetime' here because it's certain sibling of 'timestamp'
        assert (('datetime' in entry), '"datetime" key is missing from structure' + logText);

Review comment (suggestion):
so in every such method, we just `assert` value to be defined (or if null-allowed)

Code after:
                assert (typeAssertion, '"' + stringValue (key) + '" key is neither undefined, neither of expected type' + logText);
                if (deep) {
                    if (typeof value === 'object') {
                        assertStructure (exchange, skippedProperties, method, value, format[key], emptyAllowedFor, deep);
                    }
                }
            }
        }
    }
}

function assertTimestamp (exchange: Exchange, skippedProperties: object, method: string, entry: object, nowToCheck: any = undefined, keyNameOrIndex : string | number = 'timestamp', allowNull : boolean = true) {
    const logText = logTemplate (exchange, method, entry);
    const skipValue = exchange.safeValue (skippedProperties, keyNameOrIndex);
    if (skipValue !== undefined) {
        return; // skipped
    }
    const isDateTimeObject = typeof keyNameOrIndex === 'string';
    if (isDateTimeObject) {
        assert ((keyNameOrIndex in entry), 'timestamp key "' + keyNameOrIndex + '" is missing from structure' + logText);
    } else {
        // if index was provided (mostly from fetchOHLCV) then we check if it exists, as mandatory
        assert (!(entry[keyNameOrIndex] === undefined), 'timestamp index ' + stringValue (keyNameOrIndex) + ' is undefined' + logText);
    }
    const ts = entry[keyNameOrIndex];
    assert (ts !== undefined || allowNull, 'timestamp is null' + logText);
    if (ts !== undefined) {
        assert (typeof ts === 'number', 'timestamp is not numeric' + logText);
        assert (Number.isInteger (ts), 'timestamp should be an integer' + logText);
        const minTs = 1230940800000; // 03 Jan 2009 - first block
        const maxTs = 2147483648000; // 19 Jan 2038 - max int
        assert (ts > minTs, 'timestamp is impossible to be before ' + minTs.toString () + ' (03.01.2009)' + logText); // 03 Jan 2009 - first block
        assert (ts < maxTs, 'timestamp more than ' + maxTs.toString () + ' (19.01.2038)' + logText); // 19 Jan 2038 - int32 overflows // 7258118400000  -> Jan 1 2200
        if (nowToCheck !== undefined) {
            const maxMsOffset = 60000; // 1 min
            assert (ts < nowToCheck + maxMsOffset, 'returned item timestamp (' + exchange.iso8601 (ts) + ') is ahead of the current time (' + exchange.iso8601 (nowToCheck) + ')' + logText);
        }
    }
}

function assertTimestampAndDatetime (exchange: Exchange, skippedProperties: object, method: string, entry: object, nowToCheck: any = undefined, keyNameOrIndex : any = 'timestamp', allowNull : boolean = true) {
    const logText = logTemplate (exchange, method, entry);
    const skipValue = exchange.safeValue (skippedProperties, keyNameOrIndex);
    if (skipValue !== undefined) {
        return;
    }
    assertTimestamp (exchange, skippedProperties, method, entry, nowToCheck, keyNameOrIndex);
    const isDateTimeObject = typeof keyNameOrIndex === 'string';
    // only in case if the entry is a dictionary, thus it must have 'timestamp' & 'datetime' string keys
    if (isDateTimeObject) {
        // we also test 'datetime' here because it's certain sibling of 'timestamp'