Skip to content

chore: update lib architecture to use the instance in all cases. #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 85 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@
> Modern TypeScript SDK for integrating Uniswap V4 into your dapp.
> **Early version:** API may change rapidly.

---
## Features

- 🚀 Full TypeScript support
- 🔄 Multi-chain support out of the box
- 📦 Zero dependencies (except peer deps)
- 🔍 Comprehensive error handling
- 🧪 Fully tested
- 📚 Well documented

## Install

Expand All @@ -22,10 +29,10 @@ npm install uniswap-dev-kit
### 1. Configure and create SDK instances

```ts
import { createInstance } from "uniswap-dev-kit";
import { UniDevKitV4 } from "uniswap-dev-kit";

// Create instance for Ethereum mainnet
createInstance({
const ethInstance = new UniDevKitV4({
chainId: 1,
rpcUrl: "https://eth.llamarpc.com",
contracts: {
Expand All @@ -40,7 +47,7 @@ createInstance({
});

// Create instance for another chain (e.g., Base)
createInstance({
const baseInstance = new UniDevKitV4({
chainId: 8453,
rpcUrl: "https://mainnet.base.org",
contracts: {
Expand All @@ -49,96 +56,104 @@ createInstance({
});
```

The SDK automatically manages multiple instances based on chainId. When using hooks or utilities, just specify the chainId to use the corresponding instance:
### 2. Get a quote

```ts
// Will use Ethereum mainnet instance
const ethPool = await getPool({ tokens: [...] }, 1);

// Will use Base instance
const basePool = await getPool({ tokens: [...] }, 8453);
import { parseEther } from "viem";

// If you only have one instance, chainId is optional
const singleChainPool = await getPool({ tokens: [...] });
const quote = await ethInstance.getQuote({
tokens: [
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
],
feeTier: 3000,
amountIn: parseEther("1"),
zeroForOne: true
});
console.log(quote.amountOut);
```

### 2. Get a quote (vanilla JS/TS)
### 3. Get a pool

```ts
import { getQuote } from "uniswap-dev-kit";
import { parseEther } from "viem";
const pool = await ethInstance.getPool({
tokens: [
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
],
feeTier: 3000
});
console.log(pool.liquidity.toString());
```

const quote = await getQuote(
{
tokens: [
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
],
feeTier: 3000,
tickSpacing: 60,
amountIn: parseEther("1"),
},
1,
{
enabled: true,
staleTime: 30000,
gcTime: 300000,
retry: 3,
onSuccess: (data) => console.log("Quote received:", data),
},
);
console.log(quote.amountOut);
### 4. Get a position

```ts
const position = await ethInstance.getPosition({
tokenId: "123"
});
console.log({
token0: position.token0.symbol,
token1: position.token1.symbol,
liquidity: position.position.liquidity.toString()
});
```

### 3. Use in React (with hooks)
## Advanced Usage

#### Get a quote
### Error Handling

```tsx
import { useGetQuote } from "uniswap-dev-kit";
import { parseEther } from "viem";
All SDK functions include comprehensive error handling:

function QuoteComponent() {
const { data, isLoading, error } = useGetQuote({
params: {
tokens: [
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
],
feeTier: 3000,
tickSpacing: 60,
amountIn: parseEther("1"),
zeroForOne: true
},
chainId: 1
```ts
try {
const quote = await ethInstance.getQuote({
tokens: [token0, token1],
feeTier: 3000,
amountIn: parseEther("1"),
zeroForOne: true
});

if (isLoading) return <span>Loading...</span>;
if (error) return <span>Error: {error.message}</span>;
return <span>Quote: {data?.amountOut?.toString()}</span>;
} catch (error) {
// Handle specific error types
if (error.message.includes("insufficient liquidity")) {
// Handle liquidity error
} else if (error.message.includes("invalid pool")) {
// Handle pool error
}
}
```

#### Get a pool
### Using with React

You can use the SDK with React Query for data fetching:

```tsx
import { useGetPool } from "uniswap-dev-kit";
import { useQuery } from '@tanstack/react-query';
import { UniDevKitV4 } from 'uniswap-dev-kit';

function PoolComponent() {
const { data, isLoading, error } = useGetPool({
params: {
// Create instance once
const sdk = new UniDevKitV4({
chainId: 1,
rpcUrl: "https://eth.llamarpc.com",
contracts: {
// ... contract addresses
}
});

// Simple hook for quotes
function useQuote() {
return useQuery({
queryKey: ['quote'],
queryFn: () => sdk.getQuote({
tokens: [
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
],
fee: 3000,
},
chainId: 1
feeTier: 3000,
amountIn: parseEther("1"),
zeroForOne: true
})
});

if (isLoading) return <span>Loading...</span>;
if (error) return <span>Error: {error.message}</span>;
return <span>Pool: {JSON.stringify(data)}</span>;
}
```

Expand Down Expand Up @@ -173,10 +188,8 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.

## FAQ

- **Which React versions are supported?**
React 18+ (see peerDependencies)
- **Does it work in Node and browser?**
Yes, but hooks are React-only.
Yes, works in both environments.
- **Can I use my own ABIs?**
Yes, but Uniswap V4 ABIs are included.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "uniswap-dev-kit",
"version": "1.0.4",
"version": "1.0.7",
"description": "A modern TypeScript library for integrating Uniswap into your dapp.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
100 changes: 65 additions & 35 deletions src/core/uniDevKitV4.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
import { getChainById } from "@/constants/chains";
import type { UniDevKitV4Config, UniDevKitV4Instance } from "@/types/core";
import type { PoolParams } from "@/types/utils/getPool";
import type { GetPoolKeyFromPoolIdParams } from "@/types/utils/getPoolKeyFromPoolId";
import type {
GetPositionParams,
GetPositionResponse,
} from "@/types/utils/getPosition";
import type { QuoteParams, QuoteResponse } from "@/types/utils/getQuote";
import type { GetTokensParams } from "@/types/utils/getTokens";
import { getPool } from "@/utils/getPool";
import { getPoolKeyFromPoolId } from "@/utils/getPoolKeyFromPoolId";
import { getPosition } from "@/utils/getPosition";
import { getQuote } from "@/utils/getQuote";
import { getTokens } from "@/utils/getTokens";
import type { Token } from "@uniswap/sdk-core";
import type { Pool, PoolKey } from "@uniswap/v4-sdk";
import {
http,
type Address,
Expand All @@ -21,40 +36,19 @@ export class UniDevKitV4 {
* @throws Will throw an error if the configuration is invalid.
*/
constructor(config: UniDevKitV4Config) {
this.instance = this.createInstance(config);
}
const chain = getChainById(config.chainId);
const client = createPublicClient({
chain,
transport: http(config.rpcUrl || chain.rpcUrls.default.http[0]),
});

/**
* Creates a new internal instance for the SDK.
* This method is used internally to reset the instance when the configuration changes.
* @param config - The complete configuration for the SDK.
* @returns A new instance of UniDevKitV4.
*/
private createInstance(config: UniDevKitV4Config): UniDevKitV4Instance {
const client = this.createClient(config);
return {
this.instance = {
client: client as PublicClient,
chainId: config.chainId,
chain,
contracts: config.contracts,
};
}

/**
* Creates a new PublicClient for the specified chain ID and RPC URL.
* @param config - The complete configuration for the SDK.
* @returns A new PublicClient instance.
*/
private createClient(config: UniDevKitV4Config) {
const { chainId, rpcUrl } = config;

const chain = getChainById(chainId);

return createPublicClient({
chain,
transport: http(rpcUrl || chain.rpcUrls.default.http[0]),
});
}

/**
* Returns the current PublicClient instance.
* @returns The current PublicClient.
Expand All @@ -68,7 +62,7 @@ export class UniDevKitV4 {
* @returns The chain ID currently configured.
*/
getChainId(): number {
return this.instance.chainId;
return this.instance.chain.id;
}

/**
Expand All @@ -94,12 +88,48 @@ export class UniDevKitV4 {
}

/**
* Updates the SDK configuration with a complete new set of parameters.
* This method will reset the client and instance to reflect the new configuration.
* @param config - The complete configuration for the SDK.
* @throws Will throw an error if the configuration is invalid.
* Retrieves a Uniswap V4 pool instance for a given token pair.
* @param params Pool parameters including tokens, fee tier, tick spacing, and hooks configuration
* @returns Promise resolving to pool data
* @throws Error if pool data cannot be fetched
*/
updateConfig(config: UniDevKitV4Config): void {
this.instance = this.createInstance(config);
async getPool(params: PoolParams): Promise<Pool> {
return getPool(params, this.instance);
}

/**
* Retrieves token information for a given array of token addresses.
* @param params Parameters including token addresses
* @returns Promise resolving to Token instances for each token address.
* @throws Error if token data cannot be fetched
*/
async getTokens(params: GetTokensParams): Promise<Token[]> {
return getTokens(params, this.instance);
}

/**
* Retrieves a Uniswap V4 position information for a given token ID.
* @param params Position parameters including token ID
* @returns Promise resolving to position data including pool, token0, token1, poolId, and tokenId
* @throws Error if SDK instance is not found or if position data is invalid
*/
async getPosition(params: GetPositionParams): Promise<GetPositionResponse> {
return getPosition(params, this.instance);
}

/**
* Retrieves a Uniswap V4 quote for a given token pair and amount in.
* @param params Quote parameters including token pair and amount in
* @returns Promise resolving to quote data including amount out, estimated gas used, and timestamp
* @throws Error if SDK instance is not found or if quote data is invalid
*/
async getQuote(params: QuoteParams): Promise<QuoteResponse> {
return getQuote(params, this.instance);
}

async getPoolKeyFromPoolId(
params: GetPoolKeyFromPoolIdParams,
): Promise<PoolKey> {
return getPoolKeyFromPoolId(params, this.instance);
}
}
Loading