Skip to content

Commit

Permalink
Use either proxy url or Dune API key (#18)
Browse files Browse the repository at this point in the history
Enforce either API key or proxy url to be passed in (not both)
  • Loading branch information
ilamanov authored Jan 24, 2025
2 parents e507f6f + 06340a6 commit b19b2a6
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 76 deletions.
8 changes: 4 additions & 4 deletions __tests__/hooks/useEvmTokenBalances.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe("useTokenBalances", () => {
walletAddress,
{},
process.env.DUNE_API_KEY,
"https://api.dune.com"
undefined
);
expect(result.current.isLoading).toBe(false);
expect(result.current.error).toBeNull();
Expand Down Expand Up @@ -108,14 +108,14 @@ describe("useTokenBalances", () => {
walletAddress,
{},
process.env.DUNE_API_KEY,
"https://api.dune.com"
undefined
);
expect(result.current.isLoading).toBe(false);
expect(result.current.error).toEqual(mockError);
expect(result.current.data).toBeNull();
});

it("should not fetch data if the API key is missing", () => {
it("should not fetch data if the API key and proxy URL are missing", () => {
const walletAddress = "0x1234567890abcdef1234567890abcdef12345678";

const localWrapper = ({ children }: { children: React.ReactNode }) => (
Expand All @@ -129,7 +129,7 @@ describe("useTokenBalances", () => {
expect(mockFetchEvmBalances).not.toHaveBeenCalled();
expect(result.current).toEqual({
data: null,
error: null,
error: new Error("One of duneApiKey or proxyUrl must be provided"),
isLoading: false,
nextOffset: null,
offsets: [],
Expand Down
8 changes: 4 additions & 4 deletions __tests__/hooks/useEvmTransactions.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ describe("useTransactions", () => {
walletAddress,
{ offset: undefined },
process.env.DUNE_API_KEY,
"https://api.dune.com"
undefined
);
expect(result.current.data).toEqual(mockResponse);
expect(result.current.nextOffset).toBe("offset1");
Expand Down Expand Up @@ -121,7 +121,7 @@ describe("useTransactions", () => {
walletAddress,
{ offset: undefined },
process.env.DUNE_API_KEY,
"https://api.dune.com"
undefined
);
expect(result.current.error).toEqual(mockError);
expect(result.current.data).toBeNull();
Expand Down Expand Up @@ -187,7 +187,7 @@ describe("useTransactions", () => {
expect(result.current.currentPage).toBe(0);
});

it("should not fetch data if the API key is missing", () => {
it("should not fetch data if the API key and proxy URL are missing", () => {
const walletAddress = "0x1234567890abcdef1234567890abcdef12345678";

const localWrapper = ({ children }: { children: React.ReactNode }) => (
Expand All @@ -201,7 +201,7 @@ describe("useTransactions", () => {
expect(mockFetchEvmTransactions).not.toHaveBeenCalled();
expect(result.current).toEqual({
data: null,
error: null,
error: new Error("One of duneApiKey or proxyUrl must be provided"),
isLoading: false,
nextOffset: null,
offsets: [],
Expand Down
8 changes: 4 additions & 4 deletions __tests__/hooks/useSvmTokenBalances.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ describe("useTokenBalances", () => {
walletAddress,
{},
process.env.DUNE_API_KEY,
"https://api.dune.com"
undefined
);
expect(svmResult.current.isLoading).toBe(false);
expect(svmResult.current.error).toBeNull();
Expand Down Expand Up @@ -99,14 +99,14 @@ describe("useTokenBalances", () => {
walletAddress,
{},
process.env.DUNE_API_KEY,
"https://api.dune.com"
undefined
);
expect(svmResult.current.isLoading).toBe(false);
expect(svmResult.current.error).toEqual(mockError);
expect(svmResult.current.data).toBeNull();
});

it("should not fetch data if the API key is missing", () => {
it("should not fetch data if the API key and proxy URL are missing", () => {
const walletAddress = "0x1234567890abcdef1234567890abcdef12345678";

const localWrapper = ({ children }: { children: React.ReactNode }) => (
Expand All @@ -123,7 +123,7 @@ describe("useTokenBalances", () => {
expect(mockFetchSvmBalances).not.toHaveBeenCalled();
expect(svmResult.current).toEqual({
data: null,
error: null,
error: new Error("One of duneApiKey or proxyUrl must be provided"),
isLoading: false,
nextOffset: null,
offsets: [],
Expand Down
8 changes: 4 additions & 4 deletions __tests__/hooks/useSvmTransactions.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe("useTransactions", () => {
walletAddress,
{ offset: undefined },
process.env.DUNE_API_KEY,
"https://api.dune.com"
undefined
);
expect(svmResult.current.data).toEqual(mockResponse);
expect(svmResult.current.nextOffset).toBe("offset1");
Expand Down Expand Up @@ -111,7 +111,7 @@ describe("useTransactions", () => {
walletAddress,
{ offset: undefined },
process.env.DUNE_API_KEY,
"https://api.dune.com"
undefined
);
expect(svmResult.current.error).toEqual(mockError);
expect(svmResult.current.data).toBeNull();
Expand Down Expand Up @@ -180,7 +180,7 @@ describe("useTransactions", () => {
expect(svmResult.current.currentPage).toBe(0);
});

it("should not fetch data if the API key is missing", () => {
it("should not fetch data if the API key and proxy URL are missing", () => {
const walletAddress = "0x1234567890abcdef1234567890abcdef12345678";

const localWrapper = ({ children }: { children: React.ReactNode }) => (
Expand All @@ -197,7 +197,7 @@ describe("useTransactions", () => {
expect(mockFetchSvmTransactions).not.toHaveBeenCalled();
expect(svmResult.current).toEqual({
data: null,
error: null,
error: new Error("One of duneApiKey or proxyUrl must be provided"),
isLoading: false,
nextOffset: null,
offsets: [],
Expand Down
29 changes: 17 additions & 12 deletions src/evm/duneApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
TransactionsParams,
} from "./types";

const BASE_URL = "https://api.dune.com";
const BALANCES_PREFIX = "api/echo/v1/balances/evm";
const TRANSACTIONS_PREFIX = "api/echo/v1/transactions/evm";

Expand Down Expand Up @@ -36,20 +37,26 @@ const getTransactionsQueryParams = (
return queryParams;
};

const getHeaders = (duneApiKey: string | undefined) => {
return duneApiKey
? {
"x-dune-api-key": duneApiKey,
}
: undefined;
};

export async function fetchEvmBalances(
walletAddress: string,
params: TokenBalancesParams,
duneApiKey: string,
baseUrl: string
duneApiKey: string | undefined,
proxyUrl: string | undefined
): Promise<BalanceData> {
const queryParams = getBalanceQueryParams(params);
const apiUrl = `${baseUrl}/${BALANCES_PREFIX}/${walletAddress}?${queryParams.toString()}`;
const apiUrl = `${proxyUrl || BASE_URL}/${BALANCES_PREFIX}/${walletAddress}?${queryParams.toString()}`;

const response = await fetch(apiUrl, {
method: "GET",
headers: {
"x-dune-api-key": duneApiKey,
},
headers: getHeaders(duneApiKey),
});

if (!response.ok) {
Expand All @@ -65,17 +72,15 @@ export const fetchBalances = fetchEvmBalances;
export async function fetchEvmTransactions(
walletAddress: string,
params: TransactionsParams,
duneApiKey: string,
baseUrl: string
duneApiKey: string | undefined,
proxyUrl: string | undefined
): Promise<TransactionData> {
const queryParams = getTransactionsQueryParams(params);
const apiUrl = `${baseUrl}/${TRANSACTIONS_PREFIX}/${walletAddress}?${queryParams.toString()}`;
const apiUrl = `${proxyUrl || BASE_URL}/${TRANSACTIONS_PREFIX}/${walletAddress}?${queryParams.toString()}`;

const response = await fetch(apiUrl, {
method: "GET",
headers: {
"x-dune-api-key": duneApiKey,
},
headers: getHeaders(duneApiKey),
});

if (!response.ok) {
Expand Down
20 changes: 16 additions & 4 deletions src/evm/useEvmTokenBalances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useState, useEffect } from "react";
import { TokenBalancesParams, BalanceData, FetchError } from "./types";
import { fetchEvmBalances } from "./duneApi";
import { useDeepMemo } from "../useDeepMemo";
import { useGetApiKey, useGetBaseUrl } from "../provider";
import { useGetApiKey, useGetProxyUrl } from "../provider";
import { isAddress } from "viem";

export const useEvmTokenBalances = (
Expand All @@ -28,11 +28,23 @@ export const useEvmTokenBalances = (

const memoizedParams = useDeepMemo(() => params, params);
const apiKey = useGetApiKey();
const baseUrl = useGetBaseUrl();
const proxyUrl = useGetProxyUrl();

// Function to fetch data for a specific page
const fetchDataAsync = async (offset: string | null) => {
if (!apiKey || !walletAddress || !isAddress(walletAddress)) return;
if (!apiKey && !proxyUrl) {
setState({
data: null,
error: new Error("One of duneApiKey or proxyUrl must be provided"),
isLoading: false,
nextOffset: null,
offsets: [],
currentPage: 0,
});
return;
}

if (!walletAddress || !isAddress(walletAddress)) return;

setState((prevState) => ({ ...prevState, isLoading: true }));

Expand All @@ -47,7 +59,7 @@ export const useEvmTokenBalances = (
walletAddress,
updatedParams,
apiKey,
baseUrl
proxyUrl
);

setState((prevState) => ({
Expand Down
20 changes: 16 additions & 4 deletions src/evm/useEvmTransactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useState, useEffect } from "react";
import { TransactionsParams, TransactionData, FetchError } from "./types";
import { fetchEvmTransactions } from "./duneApi";
import { useDeepMemo } from "../useDeepMemo";
import { useGetApiKey, useGetBaseUrl } from "../provider";
import { useGetApiKey, useGetProxyUrl } from "../provider";
import { isAddress } from "viem";

export const useEvmTransactions = (
Expand All @@ -28,11 +28,23 @@ export const useEvmTransactions = (

const memoizedParams = useDeepMemo(() => params, [params]);
const apiKey = useGetApiKey();
const baseUrl = useGetBaseUrl();
const proxyUrl = useGetProxyUrl();

// Function to fetch data for a specific page
const fetchDataAsync = async (offset: string | null) => {
if (!apiKey || !walletAddress || !isAddress(walletAddress)) return;
if (!apiKey && !proxyUrl) {
setState({
data: null,
error: new Error("One of duneApiKey or proxyUrl must be provided"),
isLoading: false,
nextOffset: null,
offsets: [],
currentPage: 0,
});
return;
}

if (!walletAddress || !isAddress(walletAddress)) return;

setState((prevState) => ({ ...prevState, isLoading: true }));

Expand All @@ -47,7 +59,7 @@ export const useEvmTransactions = (
walletAddress,
updatedParams,
apiKey,
baseUrl
proxyUrl
);

setState((prevState) => ({
Expand Down
33 changes: 13 additions & 20 deletions src/provider.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import React, { createContext, useContext } from "react";

interface DuneContextType {
duneApiKey: string;
baseUrl?: string;
duneApiKey?: string;
proxyUrl?: string;
}

const DuneContext = createContext<DuneContextType>({
duneApiKey: "",
baseUrl: "",
});

export const useDuneContext = () => {
Expand All @@ -23,28 +22,22 @@ export const useGetApiKey = () => {
return context.duneApiKey;
};

export const useGetBaseUrl = () => {
export const useGetProxyUrl = () => {
const context = useDuneContext();
if (!context.baseUrl) {
return "https://api.dune.com";
}
return context.baseUrl;
return context.proxyUrl;
};

interface DuneProviderProps {
duneApiKey: string;
baseUrl?: string;
children: React.ReactNode;
}
type DuneProviderProps =
| { duneApiKey: string; proxyUrl?: never; children: React.ReactNode }
| { duneApiKey?: never; proxyUrl: string; children: React.ReactNode };

export const DuneProvider = (props: DuneProviderProps) => {
const duneApiKey = "duneApiKey" in props ? props.duneApiKey : undefined;
const proxyUrl = "proxyUrl" in props ? props.proxyUrl : undefined;

export const DuneProvider = ({
duneApiKey,
baseUrl,
children,
}: DuneProviderProps) => {
return (
<DuneContext.Provider value={{ duneApiKey, baseUrl }}>
{children}
<DuneContext.Provider value={{ duneApiKey, proxyUrl }}>
{props.children}
</DuneContext.Provider>
);
};
Loading

0 comments on commit b19b2a6

Please sign in to comment.