Skip to content
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
40 changes: 33 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,40 @@ const poolKey = await uniDevKit.getPoolKeyFromPoolId({
```

### `buildSwapCallData`
Construct calldata and value for a Universal Router swap.
Construct calldata for a Universal Router swap.
```ts
// Basic swap
const { calldata, value } = await uniDevKit.buildSwapCallData({
tokenIn,
tokenOut,
amountIn: "1000000000000000000",
recipient,
slippageBips: 50
tokenIn: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
amountIn: parseUnits("100", 6), // 100 USDC
pool: pool,
slippageTolerance: 50, // 0.5%
recipient: "0x..."
});

// Swap with permit2
const permitData = await uniDevKit.preparePermit2Data({
token: tokenIn,
spender: uniDevKit.getContractAddress('universalRouter'),
owner: userAddress
});

const signature = await signer._signTypedData(permitData.toSign);
const permitWithSignature = permitData.buildPermit2DataWithSignature(signature);

const { calldata: calldataWithPermit, value: valueWithPermit } = await uniDevKit.buildSwapCallData({
tokenIn: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
amountIn: parseUnits("100", 6),
pool: pool,
slippageTolerance: 50,
recipient: "0x...",
permit2Signature: permitWithSignature
});

const tx = await sendTransaction({
to: uniDevKit.getContractAddress('universalRouter'),
data: calldata,
value
});
```

Expand Down Expand Up @@ -208,4 +234,4 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
- Releases are automated with [semantic-release](https://semantic-release.gitbook.io/semantic-release/).

## License
MIT
MIT
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.9",
"version": "1.0.10",
"description": "A modern TypeScript library for integrating Uniswap into your dapp.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
22 changes: 19 additions & 3 deletions src/core/uniDevKitV4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import type { GetTokensParams } from "@/types/utils/getTokens";
import type {
PreparePermit2BatchDataParams,
PreparePermit2BatchDataResult,
} from "@/types/utils/preparePermit2BatchData";
PreparePermit2DataParams,
PreparePermit2DataResult,
} from "@/types/utils/permit2";
import { buildAddLiquidityCallData } from "@/utils/buildAddLiquidityCallData";
import { buildSwapCallData } from "@/utils/buildSwapCallData";
import { getPool } from "@/utils/getPool";
Expand All @@ -25,9 +27,10 @@ import { getPosition } from "@/utils/getPosition";
import { getQuote } from "@/utils/getQuote";
import { getTokens } from "@/utils/getTokens";
import { preparePermit2BatchData } from "@/utils/preparePermit2BatchData";
import { preparePermit2Data } from "@/utils/preparePermit2Data";
import type { Currency } from "@uniswap/sdk-core";
import type { Pool, PoolKey } from "@uniswap/v4-sdk";
import type { Abi, Address, Hex, PublicClient } from "viem";
import type { Abi, Address, PublicClient } from "viem";
import { http, createPublicClient } from "viem";

/**
Expand Down Expand Up @@ -208,7 +211,7 @@ export class UniDevKitV4 {
* @returns Promise resolving to swap call data including calldata and value
* @throws Error if SDK instance is not found or if swap call data is invalid
*/
async buildSwapCallData(params: BuildSwapCallDataParams): Promise<Hex> {
async buildSwapCallData(params: BuildSwapCallDataParams) {
return buildSwapCallData(params, this.instance);
}

Expand Down Expand Up @@ -236,4 +239,17 @@ export class UniDevKitV4 {
): Promise<PreparePermit2BatchDataResult> {
return preparePermit2BatchData(params, this.instance);
}

/**
* Prepares the permit2 simple data for a single token. (Used to swap)
* Use toSign.values to sign the permit2 simple data.
* @param params @type {PreparePermit2DataParams}
* @returns Promise resolving to permit2 simple data
* @throws Error if SDK instance is not found or if permit2 simple data is invalid
*/
async preparePermit2Data(
params: PreparePermit2DataParams,
): Promise<PreparePermit2DataResult> {
return preparePermit2Data(params, this.instance);
}
}
5 changes: 5 additions & 0 deletions src/test/utils/buildSwapCallData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ describe("buildSwapCallData", () => {
amountIn: BigInt(1000000), // 1 USDC
slippageTolerance: 50,
pool: mockPool,
recipient: zeroAddress,
};

const calldata = await buildSwapCallData(params, sdkInstance);
Expand All @@ -57,6 +58,7 @@ describe("buildSwapCallData", () => {
amountIn: BigInt(1000000000000000000), // 1 WETH
slippageTolerance: 50,
pool: mockPool,
recipient: zeroAddress,
};

const calldata = await buildSwapCallData(params, sdkInstance);
Expand All @@ -70,6 +72,7 @@ describe("buildSwapCallData", () => {
amountIn: BigInt(1000000),
slippageTolerance: 50,
pool: mockPool,
recipient: zeroAddress,
};

const calldata = await buildSwapCallData(params, sdkInstance);
Expand All @@ -83,6 +86,7 @@ describe("buildSwapCallData", () => {
amountIn: BigInt(1000000),
slippageTolerance: 50,
pool: mockPool,
recipient: zeroAddress,
};

const calldata = await buildSwapCallData(params, sdkInstance);
Expand All @@ -96,6 +100,7 @@ describe("buildSwapCallData", () => {
amountIn: BigInt(1000000),
slippageTolerance: 50,
pool: mockPool,
recipient: zeroAddress,
};

const calldata = await buildSwapCallData(params, sdkInstance);
Expand Down
14 changes: 12 additions & 2 deletions src/types/utils/buildSwapCallData.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import type { PermitSingle } from "@uniswap/permit2-sdk";
import type { Pool } from "@uniswap/v4-sdk";
import type { Address } from "viem";
import type { Address, Hex } from "viem";

/**
* Command codes for Universal Router operations
* @see https://docs.uniswap.org/contracts/universal-router/technical-reference
*/
export const COMMANDS = {
PERMIT2_PERMIT: 0x0a,
SWAP_EXACT_IN_SINGLE: 0x06,
SETTLE_ALL: 0x0c,
TAKE_ALL: 0x0f,
V4_ROUTER_EXECUTE: 0x10,
V4_SWAP: 0x10,
} as const;

/**
Expand All @@ -24,4 +26,12 @@ export type BuildSwapCallDataParams = {
pool: Pool;
/** Slippage tolerance in basis points (e.g., 50 = 0.5%). Defaults to 50 (0.5%) */
slippageTolerance?: number;
/** Recipient address */
recipient: Address;
/** Permit2 signature */
permit2Signature?: {
signature: Hex;
owner: Address;
permit: PermitSingle;
};
};
84 changes: 84 additions & 0 deletions src/types/utils/permit2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import type { PermitBatch, PermitSingle } from "@uniswap/permit2-sdk";
import type { BatchPermitOptions } from "@uniswap/v4-sdk";
import type { TypedDataField } from "ethers";
import type { Address, Hex } from "viem";

/**
* Base interface for Permit2 data
*/
interface BasePermit2Data {
/** Address that will be allowed to spend the tokens */
spender: Address | string;
/** User's wallet address */
owner: Address | string;
/** Signature deadline in seconds */
sigDeadline?: number;
}

/**
* Interface for the parameters required to generate a Permit2 batch signature
*/
export interface PreparePermit2BatchDataParams extends BasePermit2Data {
/** Array of token addresses to permit */
tokens: (Address | string)[];
}

/**
* Interface for the parameters required to generate a single Permit2 signature
*/
export interface PreparePermit2DataParams extends BasePermit2Data {
/** Token address to permit */
token: Address | string;
}

/**
* Base interface for Permit2 data result
*/
interface BasePermit2DataResult {
/** User's wallet address */
owner: Address | string;
/** Data needed to sign the permit2 data */
toSign: {
/** Domain of the permit2 data */
domain: {
name: string;
version: string;
chainId: number;
verifyingContract: `0x${string}`;
};
/** Types of the permit2 data */
types: Record<string, TypedDataField[]>;
/** Values of the permit2 data */
values: PermitBatch | PermitSingle;
/** Primary type of the permit2 data */
primaryType: "PermitBatch" | "PermitSingle";
/** Message of the permit2 data */
message: Record<string, unknown>;
};
}

/**
* Interface for the return value of the batch permit function
*/
export interface PreparePermit2BatchDataResult extends BasePermit2DataResult {
/** Function to build the permit2 batch data with a signature */
buildPermit2BatchDataWithSignature: (
signature: string | Hex,
) => BatchPermitOptions;
/** Permit2 batch data */
permitBatch: PermitBatch;
}

/**
* Interface for the return value of the single permit function
*/
export interface PreparePermit2DataResult extends BasePermit2DataResult {
/** Function to build the permit2 data with a signature */
buildPermit2DataWithSignature: (signature: Hex) => {
owner: Address;
permit: PermitSingle;
signature: Hex;
};
/** Permit2 data */
permit: PermitSingle;
}
41 changes: 0 additions & 41 deletions src/types/utils/preparePermit2BatchData.ts

This file was deleted.

Loading