Skip to content

Commit

Permalink
Merge branch 'main-v2' into fix-v2/catch-errors-getting-evm-balances
Browse files Browse the repository at this point in the history
  • Loading branch information
genaroibc authored Jun 28, 2024
2 parents 30d4780 + a6d65e1 commit 1d0c02b
Show file tree
Hide file tree
Showing 3 changed files with 292 additions and 0 deletions.
106 changes: 106 additions & 0 deletions src/handlers/evm/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,35 @@
import { Squid } from "../../index";

const mockValidateNativeBalance = jest.fn().mockResolvedValue({ isApproved: true });
const mockValidateTokenBalance = jest.fn().mockResolvedValue({ isApproved: true });
const mockValidateAllowance = jest.fn().mockResolvedValue("100000000000000000");
const mockGetGasData = jest.fn().mockResolvedValue({ gasLimit: "100" });

const testIntegratorId = "test-api";
const testBaseUrl = "https://api.uatsquidrouter.com/";

jest.mock("./utils", () => ({
Utils: class Utils {
validateNativeBalance = mockValidateNativeBalance;
validateTokenBalance = mockValidateTokenBalance;
validateAllowance = mockValidateAllowance;
getGasData = mockGetGasData;

getTokensBalanceSupportingMultiCall =
jest.requireActual("./utils").Utils.prototype.getTokensBalanceSupportingMultiCall;
getTokensBalanceWithoutMultiCall =
jest.requireActual("./utils").Utils.prototype.getTokensBalanceWithoutMultiCall;
},
}));

jest.mock("ethers", () => ({
...jest.requireActual("ethers"),
ethers: {
...jest.requireActual("ethers").ethers,
Contract: class Contract {
getEthBalance = jest.fn().mockResolvedValue("100000000000000");
balanceOf = jest.fn().mockResolvedValue("100000000");
},
},
}));

Expand Down Expand Up @@ -77,4 +98,89 @@ describe("EvmHandler", () => {
// expect();
});
});

describe("getBalances", () => {
let squid: Squid;

beforeAll(() => {
squid = new Squid({
integratorId: testIntegratorId,
baseUrl: testBaseUrl,
});

return squid.init();
});

it("returns balances for native tokens", async () => {
const ethToken = squid.tokens.find(t => t.symbol === "ETH" && t.chainId === "1");
const avaxToken = squid.tokens.find(t => t.symbol === "AVAX" && t.chainId === "43114");
const ethereumChain = squid.chains.find(c => c.chainId === "1");
const avalancheChain = squid.chains.find(c => c.chainId === "43114");

if (!ethToken || !avaxToken) throw new Error("Tokens not found");
if (!ethereumChain || !avalancheChain) throw new Error("Chain not found");

const balances = await handler.getBalances(
[ethToken, avaxToken],
"0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664",
{
"1": ethereumChain.rpc,
"43114": avalancheChain.rpc,
},
);

expect(balances).toEqual([
{
symbol: ethToken.symbol,
address: ethToken.address,
decimals: ethToken.decimals,
chainId: ethToken.chainId,
balance: "100000000000000",
},
{
symbol: avaxToken.symbol,
address: avaxToken.address,
decimals: avaxToken.decimals,
chainId: avaxToken.chainId,
balance: "100000000000000",
},
]);
});

it("returns balances for non-native tokens", async () => {
const usdcToken = squid.tokens.find(t => t.symbol === "USDC" && t.chainId === "42161");
const wethToken = squid.tokens.find(t => t.symbol === "WETH" && t.chainId === "137");
const polygonChain = squid.chains.find(c => c.chainId === "137");
const arbitrumChain = squid.chains.find(c => c.chainId === "42161");

if (!usdcToken || !wethToken) throw new Error("Tokens not found");
if (!polygonChain || !arbitrumChain) throw new Error("Chains not found");

const balances = await handler.getBalances(
[usdcToken, wethToken],
"0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664",
{
"137": polygonChain.rpc,
"42161": arbitrumChain.rpc,
},
);

expect(balances).toEqual([
{
symbol: wethToken.symbol,
address: wethToken.address,
decimals: wethToken.decimals,
chainId: wethToken.chainId,
balance: "100000000",
},
{
symbol: usdcToken.symbol,
address: usdcToken.address,
decimals: usdcToken.decimals,
chainId: usdcToken.chainId,
balance: "100000000",
},
]);
});
});
});
131 changes: 131 additions & 0 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { Squid } from "./index";

let squid: Squid;
const testIntegratorId = "test-api";
const testBaseUrl = "https://api.uatsquidrouter.com/";

describe("Squid", () => {
beforeAll(async () => {
squid = new Squid({
baseUrl: testBaseUrl,
integratorId: testIntegratorId,
});

return await squid.init();
});

describe("getTokenPrice", () => {
it("should return token price", async () => {
const tokenPrice = await squid.getTokenPrice({
tokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
chainId: "1",
});

expect(typeof tokenPrice).toEqual("number");
});

it("should return 400 error if token address is invalid", async () => {
try {
await squid.getTokenPrice({
tokenAddress: "0x",
chainId: "1",
});
} catch (error) {
expect(error.response.status).toEqual(400);
}
});

it("should return 400 error if chain id is invalid", async () => {
try {
await squid.getTokenPrice({
tokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
chainId: "",
});
} catch (error) {
expect(error.response.status).toEqual(400);
}
});
});

describe("getMultipleTokensPrice", () => {
it("should return price for multiple tokens", async () => {
const tokensWithPrice = await squid.getMultipleTokensPrice({
chainId: "1",
});

expect(tokensWithPrice.every(tokenPrice => typeof tokenPrice.usdPrice === "number")).toBe(
true,
);
});
});

describe("getRoute", () => {
it("should return route", async () => {
const { route, integratorId, requestId } = await squid.getRoute({
fromChain: "1",
toChain: "56",
fromToken: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
toToken: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
fromAddress: "0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5",
toAddress: "0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5",
fromAmount: "5000000000000",
slippage: 1.5,
});

expect(route.estimate).toBeDefined();
expect(route.params).toBeDefined();
expect(integratorId).toEqual(testIntegratorId);
expect(requestId).toBeDefined();
});

it("should return 400 error if from or to address not provided", async () => {
try {
await squid.getRoute({
fromChain: "1",
toChain: "56",
fromToken: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
toToken: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
fromAmount: "5000000000000",
slippage: 1.5,
});
} catch (error) {
expect(error.response.status).toEqual(400);
}
});
});

describe("getStatus", () => {
jest.setTimeout(10000); // increase timeout for slow tests to 10 seconds

it("should return 404 error if transactionId is invalid", async () => {
try {
await squid.getStatus({
requestId: "1643a99ae59c3f5164ed120812f00e38",
integratorId: testIntegratorId,
transactionId: "0x",
});

expect(true).toBe(false); // should fail before reaching here
} catch (error) {
expect(error.response.status).toEqual(404);
expect(error.response.data.message).toEqual("No transaction found in axelarscan");
}
});

it("should return 400 error if transactionId is missing", async () => {
try {
await squid.getStatus({
requestId: "0x",
integratorId: testIntegratorId,
transactionId: "",
});

expect(true).toBe(false); // should fail before reaching here
} catch (error) {
expect(error.response.status).toEqual(400);
expect(error.response.data.message).toEqual("transactionId is a required field");
expect(error.response.data.type).toEqual("SCHEMA_VALIDATION_ERROR");
}
});
});
});
55 changes: 55 additions & 0 deletions src/utils/TokensChains.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { TokensChains } from "./TokensChains";
import { Squid } from "../index";

const tokenChains = new TokensChains();

const testIntegratorId = "test-api";
const testBaseUrl = "https://api.uatsquidrouter.com/";

describe("TokensChains", () => {
let squid: Squid;

beforeAll(async () => {
squid = new Squid({
integratorId: testIntegratorId,
baseUrl: testBaseUrl,
});

await squid.init();

tokenChains.tokens = squid.tokens;
tokenChains.chains = squid.chains;
});

describe("getChainData", () => {
it("should return chain data", async () => {
const chain = squid.chains.find(c => c.chainId === "1");

if (!chain) throw new Error("Chain not found");

const chainData = tokenChains.getChainData(chain.chainId);

expect(chainData).toEqual(chain);
});

it("should throw error if chain not found", async () => {
expect(() => tokenChains.getChainData("9999999")).toThrowError();
});
});

describe("getTokenData", () => {
it("should return token data", async () => {
const token = squid.tokens.find(t => t.symbol === "WETH" && t.chainId === "1");

if (!token) throw new Error("Token not found");

const tokenData = tokenChains.getTokenData(token.address, token.chainId);

expect(tokenData).toEqual(token);
});

it("should throw error if token not found", async () => {
expect(() => tokenChains.getTokenData("0x", "1")).toThrowError();
});
});
});

0 comments on commit 1d0c02b

Please sign in to comment.