Skip to content

Commit 8f66c86

Browse files
authored
Merge pull request #13 from BootNodeDev/fix/permitBatch
feat: add permit single to swapCallData
2 parents f4f3a18 + f08fdc6 commit 8f66c86

File tree

11 files changed

+524
-113
lines changed

11 files changed

+524
-113
lines changed

README.md

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,40 @@ const poolKey = await uniDevKit.getPoolKeyFromPoolId({
125125
```
126126

127127
### `buildSwapCallData`
128-
Construct calldata and value for a Universal Router swap.
128+
Construct calldata for a Universal Router swap.
129129
```ts
130+
// Basic swap
130131
const { calldata, value } = await uniDevKit.buildSwapCallData({
131-
tokenIn,
132-
tokenOut,
133-
amountIn: "1000000000000000000",
134-
recipient,
135-
slippageBips: 50
132+
tokenIn: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
133+
amountIn: parseUnits("100", 6), // 100 USDC
134+
pool: pool,
135+
slippageTolerance: 50, // 0.5%
136+
recipient: "0x..."
137+
});
138+
139+
// Swap with permit2
140+
const permitData = await uniDevKit.preparePermit2Data({
141+
token: tokenIn,
142+
spender: uniDevKit.getContractAddress('universalRouter'),
143+
owner: userAddress
144+
});
145+
146+
const signature = await signer._signTypedData(permitData.toSign);
147+
const permitWithSignature = permitData.buildPermit2DataWithSignature(signature);
148+
149+
const { calldata: calldataWithPermit, value: valueWithPermit } = await uniDevKit.buildSwapCallData({
150+
tokenIn: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
151+
amountIn: parseUnits("100", 6),
152+
pool: pool,
153+
slippageTolerance: 50,
154+
recipient: "0x...",
155+
permit2Signature: permitWithSignature
156+
});
157+
158+
const tx = await sendTransaction({
159+
to: uniDevKit.getContractAddress('universalRouter'),
160+
data: calldata,
161+
value
136162
});
137163
```
138164

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

210236
## License
211-
MIT
237+
MIT

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "uniswap-dev-kit",
3-
"version": "1.0.9",
3+
"version": "1.0.10",
44
"description": "A modern TypeScript library for integrating Uniswap into your dapp.",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

src/core/uniDevKitV4.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import type { GetTokensParams } from "@/types/utils/getTokens";
1616
import type {
1717
PreparePermit2BatchDataParams,
1818
PreparePermit2BatchDataResult,
19-
} from "@/types/utils/preparePermit2BatchData";
19+
PreparePermit2DataParams,
20+
PreparePermit2DataResult,
21+
} from "@/types/utils/permit2";
2022
import { buildAddLiquidityCallData } from "@/utils/buildAddLiquidityCallData";
2123
import { buildSwapCallData } from "@/utils/buildSwapCallData";
2224
import { getPool } from "@/utils/getPool";
@@ -25,9 +27,10 @@ import { getPosition } from "@/utils/getPosition";
2527
import { getQuote } from "@/utils/getQuote";
2628
import { getTokens } from "@/utils/getTokens";
2729
import { preparePermit2BatchData } from "@/utils/preparePermit2BatchData";
30+
import { preparePermit2Data } from "@/utils/preparePermit2Data";
2831
import type { Currency } from "@uniswap/sdk-core";
2932
import type { Pool, PoolKey } from "@uniswap/v4-sdk";
30-
import type { Abi, Address, Hex, PublicClient } from "viem";
33+
import type { Abi, Address, PublicClient } from "viem";
3134
import { http, createPublicClient } from "viem";
3235

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

@@ -236,4 +239,17 @@ export class UniDevKitV4 {
236239
): Promise<PreparePermit2BatchDataResult> {
237240
return preparePermit2BatchData(params, this.instance);
238241
}
242+
243+
/**
244+
* Prepares the permit2 simple data for a single token. (Used to swap)
245+
* Use toSign.values to sign the permit2 simple data.
246+
* @param params @type {PreparePermit2DataParams}
247+
* @returns Promise resolving to permit2 simple data
248+
* @throws Error if SDK instance is not found or if permit2 simple data is invalid
249+
*/
250+
async preparePermit2Data(
251+
params: PreparePermit2DataParams,
252+
): Promise<PreparePermit2DataResult> {
253+
return preparePermit2Data(params, this.instance);
254+
}
239255
}

src/test/utils/buildSwapCallData.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ describe("buildSwapCallData", () => {
4444
amountIn: BigInt(1000000), // 1 USDC
4545
slippageTolerance: 50,
4646
pool: mockPool,
47+
recipient: zeroAddress,
4748
};
4849

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

6264
const calldata = await buildSwapCallData(params, sdkInstance);
@@ -70,6 +72,7 @@ describe("buildSwapCallData", () => {
7072
amountIn: BigInt(1000000),
7173
slippageTolerance: 50,
7274
pool: mockPool,
75+
recipient: zeroAddress,
7376
};
7477

7578
const calldata = await buildSwapCallData(params, sdkInstance);
@@ -83,6 +86,7 @@ describe("buildSwapCallData", () => {
8386
amountIn: BigInt(1000000),
8487
slippageTolerance: 50,
8588
pool: mockPool,
89+
recipient: zeroAddress,
8690
};
8791

8892
const calldata = await buildSwapCallData(params, sdkInstance);
@@ -96,6 +100,7 @@ describe("buildSwapCallData", () => {
96100
amountIn: BigInt(1000000),
97101
slippageTolerance: 50,
98102
pool: mockPool,
103+
recipient: zeroAddress,
99104
};
100105

101106
const calldata = await buildSwapCallData(params, sdkInstance);

src/types/utils/buildSwapCallData.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1+
import type { PermitSingle } from "@uniswap/permit2-sdk";
12
import type { Pool } from "@uniswap/v4-sdk";
2-
import type { Address } from "viem";
3+
import type { Address, Hex } from "viem";
34

45
/**
56
* Command codes for Universal Router operations
67
* @see https://docs.uniswap.org/contracts/universal-router/technical-reference
78
*/
89
export const COMMANDS = {
10+
PERMIT2_PERMIT: 0x0a,
911
SWAP_EXACT_IN_SINGLE: 0x06,
1012
SETTLE_ALL: 0x0c,
1113
TAKE_ALL: 0x0f,
12-
V4_ROUTER_EXECUTE: 0x10,
14+
V4_SWAP: 0x10,
1315
} as const;
1416

1517
/**
@@ -24,4 +26,12 @@ export type BuildSwapCallDataParams = {
2426
pool: Pool;
2527
/** Slippage tolerance in basis points (e.g., 50 = 0.5%). Defaults to 50 (0.5%) */
2628
slippageTolerance?: number;
29+
/** Recipient address */
30+
recipient: Address;
31+
/** Permit2 signature */
32+
permit2Signature?: {
33+
signature: Hex;
34+
owner: Address;
35+
permit: PermitSingle;
36+
};
2737
};

src/types/utils/permit2.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import type { PermitBatch, PermitSingle } from "@uniswap/permit2-sdk";
2+
import type { BatchPermitOptions } from "@uniswap/v4-sdk";
3+
import type { TypedDataField } from "ethers";
4+
import type { Address, Hex } from "viem";
5+
6+
/**
7+
* Base interface for Permit2 data
8+
*/
9+
interface BasePermit2Data {
10+
/** Address that will be allowed to spend the tokens */
11+
spender: Address | string;
12+
/** User's wallet address */
13+
owner: Address | string;
14+
/** Signature deadline in seconds */
15+
sigDeadline?: number;
16+
}
17+
18+
/**
19+
* Interface for the parameters required to generate a Permit2 batch signature
20+
*/
21+
export interface PreparePermit2BatchDataParams extends BasePermit2Data {
22+
/** Array of token addresses to permit */
23+
tokens: (Address | string)[];
24+
}
25+
26+
/**
27+
* Interface for the parameters required to generate a single Permit2 signature
28+
*/
29+
export interface PreparePermit2DataParams extends BasePermit2Data {
30+
/** Token address to permit */
31+
token: Address | string;
32+
}
33+
34+
/**
35+
* Base interface for Permit2 data result
36+
*/
37+
interface BasePermit2DataResult {
38+
/** User's wallet address */
39+
owner: Address | string;
40+
/** Data needed to sign the permit2 data */
41+
toSign: {
42+
/** Domain of the permit2 data */
43+
domain: {
44+
name: string;
45+
version: string;
46+
chainId: number;
47+
verifyingContract: `0x${string}`;
48+
};
49+
/** Types of the permit2 data */
50+
types: Record<string, TypedDataField[]>;
51+
/** Values of the permit2 data */
52+
values: PermitBatch | PermitSingle;
53+
/** Primary type of the permit2 data */
54+
primaryType: "PermitBatch" | "PermitSingle";
55+
/** Message of the permit2 data */
56+
message: Record<string, unknown>;
57+
};
58+
}
59+
60+
/**
61+
* Interface for the return value of the batch permit function
62+
*/
63+
export interface PreparePermit2BatchDataResult extends BasePermit2DataResult {
64+
/** Function to build the permit2 batch data with a signature */
65+
buildPermit2BatchDataWithSignature: (
66+
signature: string | Hex,
67+
) => BatchPermitOptions;
68+
/** Permit2 batch data */
69+
permitBatch: PermitBatch;
70+
}
71+
72+
/**
73+
* Interface for the return value of the single permit function
74+
*/
75+
export interface PreparePermit2DataResult extends BasePermit2DataResult {
76+
/** Function to build the permit2 data with a signature */
77+
buildPermit2DataWithSignature: (signature: Hex) => {
78+
owner: Address;
79+
permit: PermitSingle;
80+
signature: Hex;
81+
};
82+
/** Permit2 data */
83+
permit: PermitSingle;
84+
}

src/types/utils/preparePermit2BatchData.ts

Lines changed: 0 additions & 41 deletions
This file was deleted.

0 commit comments

Comments
 (0)