@stabilis/c9-shape-liquidity-getter
Version:
A library for calculating redemption values of concentrated liquidity positions for C9 shape liquidity.
436 lines (435 loc) • 27 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const redemption_service_1 = require("../services/redemption.service");
const test_config_1 = require("./test.config");
const errors_1 = require("../types/errors");
const errors_2 = require("../types/errors");
describe("Redemption Service Tests", () => {
// Set longer timeout for real network calls
jest.setTimeout(30000);
describe("getRedemptionValue", () => {
test("should successfully calculate redemption value with valid inputs", async () => {
const result = await (0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
});
console.log("\nValid inputs result:", result);
expect(result).not.toBeNull();
expect(result).toHaveProperty("xToken");
expect(result).toHaveProperty("yToken");
expect(result).toHaveProperty("isActive");
expect(typeof result?.xToken).toBe("string");
expect(typeof result?.yToken).toBe("string");
expect(typeof result?.isActive).toBe("boolean");
});
test("should output values with exactly 18 decimal places", async () => {
const result = await (0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
});
expect(result).not.toBeNull();
// Check if xToken has exactly 18 decimal places
const xTokenParts = result.xToken.split('.');
if (xTokenParts.length > 1) {
expect(xTokenParts[1].length).toBe(18);
}
else {
// For integers, should end with 18 zeros
expect(result.xToken.endsWith('.000000000000000000')).toBe(true);
}
// Check if yToken has exactly 18 decimal places
const yTokenParts = result.yToken.split('.');
if (yTokenParts.length > 1) {
expect(yTokenParts[1].length).toBe(18);
}
else {
// For integers, should end with 18 zeros
expect(result.yToken.endsWith('.000000000000000000')).toBe(true);
}
});
test("should handle wrong type component address", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.wrongTypeComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
})).rejects.toThrow("Invalid component address: 123");
});
test("should handle random string component address", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.randomStringComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
})).rejects.toThrow(errors_1.ComponentError);
});
test("should handle real non-C9 component address", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.realNonC9ComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
})).rejects.toThrow(errors_1.ComponentError);
});
test("should handle wrong type NFT ID", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.wrongTypeNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
})).rejects.toThrow("Invalid NFT ID: 456");
});
test("should handle random string NFT ID", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.randomStringNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
})).rejects.toThrow(errors_1.NFTError);
});
test("should handle non-existent NFT ID", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.nonExistentNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
})).rejects.toThrow(errors_1.NFTError);
});
test("should handle early state version", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.earlyStateVersion,
})).rejects.toThrow(errors_1.ComponentError);
});
test("should handle future state version", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.futureStateVersion,
})).rejects.toThrow(errors_1.DataError);
});
describe("price bounds", () => {
test("should successfully calculate redemption value with valid price bounds", async () => {
const result = await (0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.validPriceBounds,
});
expect(result).not.toBeNull();
expect(result).toHaveProperty("xToken");
expect(result).toHaveProperty("yToken");
expect(typeof result?.xToken).toBe("string");
expect(typeof result?.yToken).toBe("string");
});
test("should successfully calculate redemption value with valid price bounds and middle price", async () => {
const result = await (0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.validPriceBounds,
middlePrice: test_config_1.TEST_CONFIG.validMiddlePrice,
});
expect(result).not.toBeNull();
expect(result).toHaveProperty("xToken");
expect(result).toHaveProperty("yToken");
expect(typeof result?.xToken).toBe("string");
expect(typeof result?.yToken).toBe("string");
});
test("should handle wrong type price bounds", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.invalidPriceBounds.wrongType,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle wrong length price bounds", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.invalidPriceBounds.wrongLength,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle negative multiplier in price bounds", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.invalidPriceBounds.negativeMultiplier,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle zero multiplier in price bounds", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.invalidPriceBounds.zeroMultiplier,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle reversed order price bounds", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.invalidPriceBounds.reversedOrder,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle equal values in price bounds", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.invalidPriceBounds.equalValues,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle wrong type middle price", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.validPriceBounds,
middlePrice: test_config_1.TEST_CONFIG.invalidMiddlePrice.wrongType,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle negative middle price", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.validPriceBounds,
middlePrice: test_config_1.TEST_CONFIG.invalidMiddlePrice.negative,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle zero middle price", async () => {
await expect((0, redemption_service_1.getRedemptionValue)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftId: test_config_1.TEST_CONFIG.validNftId,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.validPriceBounds,
middlePrice: test_config_1.TEST_CONFIG.invalidMiddlePrice.zero,
})).rejects.toThrow(errors_2.ValidationError);
});
});
});
describe("getRedemptionValues", () => {
test("should successfully calculate redemption values with valid inputs", async () => {
const result = await (0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
});
console.log("\nValid inputs batch result:", result);
expect(result).toBeDefined();
expect(Object.keys(result).length).toBeGreaterThan(0);
for (const nftId of test_config_1.TEST_CONFIG.validNftIds) {
expect(result[nftId]).toBeDefined();
expect(result[nftId]).toHaveProperty("xToken");
expect(result[nftId]).toHaveProperty("yToken");
expect(result[nftId]).toHaveProperty("isActive");
expect(typeof result[nftId].xToken).toBe("string");
expect(typeof result[nftId].yToken).toBe("string");
expect(typeof result[nftId].isActive).toBe("boolean");
}
});
test("should output all values with exactly 18 decimal places in batch mode", async () => {
const result = await (0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
});
expect(result).toBeDefined();
expect(Object.keys(result).length).toBeGreaterThan(0);
for (const nftId of test_config_1.TEST_CONFIG.validNftIds) {
expect(result[nftId]).toBeDefined();
// Check if xToken has exactly 18 decimal places
const xTokenParts = result[nftId].xToken.split('.');
if (xTokenParts.length > 1) {
expect(xTokenParts[1].length).toBe(18);
}
else {
// For integers, should end with 18 zeros
expect(result[nftId].xToken.endsWith('.000000000000000000')).toBe(true);
}
// Check if yToken has exactly 18 decimal places
const yTokenParts = result[nftId].yToken.split('.');
if (yTokenParts.length > 1) {
expect(yTokenParts[1].length).toBe(18);
}
else {
// For integers, should end with 18 zeros
expect(result[nftId].yToken.endsWith('.000000000000000000')).toBe(true);
}
}
});
test("should handle wrong type component address", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.wrongTypeComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
})).rejects.toThrow("Invalid component address: 123");
});
test("should handle random string component address", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.randomStringComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
})).rejects.toThrow(errors_1.ComponentError);
});
test("should handle real non-C9 component address", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.realNonC9ComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
})).rejects.toThrow(errors_1.ComponentError);
});
test("should handle one invalid NFT ID in batch", async () => {
const result = await (0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.mixedNftIds.oneInvalid,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
});
console.log("\nOne invalid NFT ID in batch result:", result);
expect(result).toBeDefined();
expect(Object.keys(result).length).toBeLessThan(test_config_1.TEST_CONFIG.mixedNftIds.oneInvalid.length);
// Valid NFTs should still have results
const validNftId = test_config_1.TEST_CONFIG.mixedNftIds.oneInvalid[0];
expect(result[validNftId]).toBeDefined();
expect(result[validNftId]).toHaveProperty("xToken");
expect(result[validNftId]).toHaveProperty("yToken");
});
test("should handle all invalid NFT IDs", async () => {
const result = await (0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.mixedNftIds.allInvalid,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
});
console.log("\nAll invalid NFT IDs result:", result);
expect(result).toEqual({});
});
test("should handle early state version", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.earlyStateVersion,
})).rejects.toThrow(errors_1.ComponentError);
});
test("should handle future state version", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.futureStateVersion,
})).rejects.toThrow(errors_1.DataError);
});
describe("price bounds", () => {
test("should successfully calculate redemption values with valid price bounds", async () => {
const result = await (0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.validPriceBounds,
});
expect(result).toBeDefined();
expect(Object.keys(result).length).toBeGreaterThan(0);
for (const nftId of test_config_1.TEST_CONFIG.validNftIds) {
expect(result[nftId]).toBeDefined();
expect(result[nftId]).toHaveProperty("xToken");
expect(result[nftId]).toHaveProperty("yToken");
expect(typeof result[nftId].xToken).toBe("string");
expect(typeof result[nftId].yToken).toBe("string");
}
});
test("should successfully calculate redemption values with valid price bounds and middle price", async () => {
const result = await (0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.validPriceBounds,
middlePrice: test_config_1.TEST_CONFIG.validMiddlePrice,
});
expect(result).toBeDefined();
expect(Object.keys(result).length).toBeGreaterThan(0);
for (const nftId of test_config_1.TEST_CONFIG.validNftIds) {
expect(result[nftId]).toBeDefined();
expect(result[nftId]).toHaveProperty("xToken");
expect(result[nftId]).toHaveProperty("yToken");
expect(typeof result[nftId].xToken).toBe("string");
expect(typeof result[nftId].yToken).toBe("string");
}
});
test("should handle wrong type price bounds", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.invalidPriceBounds.wrongType,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle wrong length price bounds", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.invalidPriceBounds.wrongLength,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle negative multiplier in price bounds", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.invalidPriceBounds.negativeMultiplier,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle zero multiplier in price bounds", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.invalidPriceBounds.zeroMultiplier,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle reversed order price bounds", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.invalidPriceBounds.reversedOrder,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle equal values in price bounds", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.invalidPriceBounds.equalValues,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle wrong type middle price", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.validPriceBounds,
middlePrice: test_config_1.TEST_CONFIG.invalidMiddlePrice.wrongType,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle negative middle price", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.validPriceBounds,
middlePrice: test_config_1.TEST_CONFIG.invalidMiddlePrice.negative,
})).rejects.toThrow(errors_2.ValidationError);
});
test("should handle zero middle price", async () => {
await expect((0, redemption_service_1.getRedemptionValues)({
componentAddress: test_config_1.TEST_CONFIG.validComponentAddress,
nftIds: test_config_1.TEST_CONFIG.validNftIds,
stateVersion: test_config_1.TEST_CONFIG.validStateVersion,
priceBounds: test_config_1.TEST_CONFIG.validPriceBounds,
middlePrice: test_config_1.TEST_CONFIG.invalidMiddlePrice.zero,
})).rejects.toThrow(errors_2.ValidationError);
});
});
});
});