UNPKG

@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
"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); }); }); }); });