### Install Dependencies and Verify Setup Source: https://developers.uniswap.org/docs/uniswap-ai/contributions Ensure you have the correct npm version installed globally. Then, install project dependencies and verify the setup by running tests, building packages, and starting the documentation server. ```bash # Ensure you have the correct npm version npm install -g npm@11.7.0 # Install dependencies npm install ``` ```bash # Run tests npx nx run-many --target=test # Build all packages npx nx run-many --target=build # Start docs dev server bun dev-portal dev ``` -------------------------------- ### Setup React App and Install Dependencies Source: https://developers.uniswap.org/docs/ecosystem/subgraphs/guides/using-subgraphs Create a new React application using create-react-app and install necessary dependencies for interacting with GraphQL. ```bash yarn create react-app uniswap-demo cd uniswap-demo yarn add apollo-client apollo-cache-inmemory apollo-link-http graphql graphql-tag @apollo/react-hooks yarn start ``` -------------------------------- ### Run Tycho Simulation Quickstart Source: https://developers.uniswap.org/docs/unichain/guides/routing-on-unichain Execute the quickstart example to simulate a trade on Unichain liquidity. Ensure you set the necessary environment variables for RPC URL, Tycho URL, API key, and your private key. ```bash export RPC_URL=https://unichain-rpc.publicnode.com export TYCHO_URL=tycho-unichain-beta.propellerheads.xyz export TYCHO_API_KEY=sampletoken export PRIVATE_KEY=YOUR_TEST_WALLET_PRIVATE_KEY cargo run --release --example quickstart -- --sell-token "0x078D782b760474a361dDA0AF3839290b0EF57AD6" --buy-token "0x4200000000000000000000000000000000000006" --sell-amount 10 --chain "unichain" --swapper-pk $PRIVATE_KEY ``` -------------------------------- ### Tycho Simulation Example Output Source: https://developers.uniswap.org/docs/unichain/guides/routing-on-unichain This is an example output from the Tycho simulation quickstart. It shows the process of finding the best swap price, simulating the trade, and executing the approval and swap transactions. ```text Loading tokens from Tycho... tycho-unichain-beta.propellerheads.xyz Tokens loaded: 7333 Looking for pool with best price for 10 USDC -> WETH ==================== Received block 14142597 ==================== The best swap (out of 1 possible pools) is: Protocol: "uniswap_v3" Pool address: "0x65081cb48d74a32e9ccfed75164b8c09972dbcf1" Swap: 10.000000 USDC -> 0.006268 WETH Price: 0.000627 WETH per USDC, 1595.468182 USDC per WETH Would you like to simulate or execute this swap? ✔ What would you like to do? · Execute the swap Executing by performing an approval (for permit2) and a swap transaction... Approval transaction sent with hash: 0x091f973337b77202c62baa97e81207882a4d93903fc21a4061e3b0d6fb5c0ab1 and status: true Swap transaction sent with hash: 0xe8f5f73023c46080eb59efce5535228f19cafdc5f8ff01cba91678eee550b589 and status: true ``` -------------------------------- ### Install Uniswap V4 SDK Packages Source: https://developers.uniswap.org/docs/get-started/quickstart Install the necessary packages for using the Uniswap V4 SDK guides. ```bash npm install @uniswap/v4-sdk npm install @uniswap/sdk-core npm install @uniswap/universal-router-sdk ``` -------------------------------- ### Install Core SDK and viem Source: https://developers.uniswap.org/docs/community/tooling/community-sdk Install the core SDK and viem for interacting with Ethereum. ```bash pnpm install @zahastudio/uniswap-sdk viem ``` -------------------------------- ### Start Development Server Source: https://developers.uniswap.org/docs/unichain/guides/transfer-usdc Run this command to start the development server for your application. ```bash npm run dev ``` -------------------------------- ### Install Foundry Source: https://developers.uniswap.org/docs/unichain/guides/create-a-pool Install Foundry, a smart contract development toolkit, by running this command. ```bash curl -L https://foundry.paradigm.xyz | bash ``` -------------------------------- ### Example Contract Setup with Uniswap v4 Interfaces Source: https://developers.uniswap.org/docs/protocols/v4/guides/swapping/routing Define a Solidity contract that imports and initializes interfaces for UniversalRouter, PoolManager, and Permit2. ```solidity // SPDX-License-Identifier: MIT pragma solidity 0.8.26; import { IUniversalRouter } from "@uniswap/universal-router/contracts/interfaces/IUniversalRouter.sol"; import { Commands } from "@uniswap/universal-router/contracts/libraries/Commands.sol"; import { IPoolManager } from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import { IV4Router } from "@uniswap/v4-periphery/src/interfaces/IV4Router.sol"; import { Actions } from "@uniswap/v4-periphery/src/libraries/Actions.sol"; import { IPermit2 } from "@uniswap/permit2/src/interfaces/IPermit2.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { StateLibrary } from "@uniswap/v4-core/src/libraries/StateLibrary.sol"; import { PoolKey } from "@uniswap/v4-core/src/types/PoolKey.sol"; import { Currency } from "@uniswap/v4-core/src/types/Currency.sol"; contract Example { using StateLibrary for IPoolManager; IUniversalRouter public immutable router; IPoolManager public immutable poolManager; IPermit2 public immutable permit2; constructor(address _router, address _poolManager, address _permit2) { router = IUniversalRouter(_router); poolManager = IPoolManager(_poolManager); permit2 = IPermit2(_permit2); } // We'll add more functions here } ``` -------------------------------- ### Setup for Uniswap v4 SDK Source: https://developers.uniswap.org/docs/sdks/v4/guides/managing-liquidity/position-fetching Initializes the viem public client and defines the Position Manager address for Unichain. Ensure you have the necessary viem and subgraph packages installed. ```typescript import { createPublicClient, http, Address, zeroAddress } from 'viem' import { unichain } from 'viem/chains' import request from 'graphql-request' const POSITION_MANAGER_ADDRESS = '0x4529a01c7a0410167c5740c487a8de60232617bf' //unichain const publicClient = createPublicClient({ chain: unichain, transport: http(), }) ``` -------------------------------- ### Clone and Install v4 Template Source: https://developers.uniswap.org/docs/protocols/v4/guides/hooks/getting-started Clone the v4-template repository and install its dependencies using Foundry. This is a quick way to get started with a pre-configured environment. ```bash git clone https://github.com/uniswapfoundation/v4-template.git cd v4-template # requires foundry forge install forge test ``` -------------------------------- ### Define Example Configuration Source: https://developers.uniswap.org/docs/sdks/v4/guides/pool-data Set up an example configuration object including environment, RPC endpoints, and pool key details. ```typescript export const CurrentConfig: ExampleConfig = { env: Environment.MAINNET, rpc: { local: 'http://localhost:8545', mainnet: 'https://mainnet.infura.io/v3/YOUR_API_KEY', }, ... poolKey: { currency0: ETH_TOKEN.address, currency1: USDC_TOKEN.address, fee: FEE_AMOUNT_LOW, tickSpacing: TICK_SPACING_TEN, hooks: EMPTY_HOOK, }, } ``` -------------------------------- ### Uniswap API Swapping Example (Ethers) Source: https://developers.uniswap.org/docs/trading/swapping-api/swapping-code-examples This example demonstrates the complete flow of checking approval, getting a quote, and executing a swap using the Uniswap API with Ethers. Ensure you have the necessary API key and provider setup. ```javascript const API_KEY = '' const API_URL = 'https://trade-api.gateway.uniswap.org/v1' const headers = { 'x-api-key': API_KEY, 'accept': 'application/json', 'content-type': 'application/json', } const signer = provider.getSigner() // APPROVAL const approvalResponse = await axios.post( `${API_URL}/check_approval`, { walletAddress: await signer.getAddress(), amount: BigNumber.from(amount).mul(2).toString(), token: tokenIn, chainId: 1, tokenOut: tokenOut, tokenOutChainId: 1, }, { headers, } ) if (approvalResponse.data.approval) { await signer.sendTransaction(approvalResponse.data.approval) } // QUOTE const quoteResponse = await axios.post( `${API_URL}/quote`, { swapper: await signer.getAddress(), tokenInChainId: 1, tokenOutChainId: 1, tokenIn: tokenIn, tokenOut: tokenOut, amount: amount, routingPreference: routingPreference, type: 'EXACT_INPUT', }, { headers, } ) const { quote, permitData, routing } = quoteResponse.data let signature if (permitData) { signature = await signer._signTypedData(permitData.domain, permitData.types, permitData.values) } //ORDER let postTransactionResponse if (routing === 'CLASSIC' || routing === 'WRAP' || routing === 'UNWRAP' || routing === 'BRIDGE') { postTransactionResponse = await axios.post( `${API_URL}/swap`, { signature: signature, quote: quote, permitData: permitData, }, { headers, } ) await signer.sendTransaction(postTransactionResponse.data.swap) } else if (routing === 'DUTCH_V2' || routing === 'DUTCH_V3' || routing === 'PRIORITY') { postTransactionResponse = await axios.post( `${API_URL}/order`, { signature: signature, quote: quote, }, { headers, } ) } ``` -------------------------------- ### Install Dependencies Source: https://developers.uniswap.org/docs/unichain/guides/transfer-usdc Install necessary libraries including viem for blockchain interaction and UI components from Radix UI and Lucide React. ```bash npm install viem @radix-ui/react-slot @radix-ui/react-tabs lucide-react ``` -------------------------------- ### Install OpenZeppelin Uniswap Hooks Source: https://developers.uniswap.org/docs/community/tooling/openzeppelin Install the library using forge and add the remapping to your remappings.txt file. ```bash forge install OpenZeppelin/uniswap-hooks ``` ```plaintext @openzeppelin/uniswap-hooks/=lib/uniswap-hooks/src/ ``` -------------------------------- ### Install Interop-lib Source: https://developers.uniswap.org/docs/unichain/guides/deploy-a-superchain-erc20 Installs Optimism's Interop-lib, which contains the SuperchainERC20 implementation. ```bash forge install ethereum-optimism/interop-lib ``` -------------------------------- ### Set up Example contract with Uniswap v4 dependencies Source: https://developers.uniswap.org/docs/protocols/v4/guides/swapping/swapping Initializes the Example contract with addresses for UniversalRouter, PoolManager, and Permit2. Imports necessary interfaces and libraries for v4 interactions. ```solidity // SPDX-License-Identifier: MIT pragma solidity 0.8.26; import { UniversalRouter } from "@uniswap/universal-router/contracts/UniversalRouter.sol"; import { Commands } from "@uniswap/universal-router/contracts/libraries/Commands.sol"; import { IPoolManager } from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import { IV4Router } from "@uniswap/v4-periphery/src/interfaces/IV4Router.sol"; import { Actions } from "@uniswap/v4-periphery/src/libraries/Actions.sol"; import { IPermit2 } from "@uniswap/permit2/src/interfaces/IPermit2.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { StateLibrary } from "@uniswap/v4-core/src/libraries/StateLibrary.sol"; import { PoolKey } from "@uniswap/v4-core/src/types/PoolKey.sol"; import { Currency } from "@uniswap/v4-core/src/types/Currency.sol"; contract Example { using StateLibrary for IPoolManager; UniversalRouter public immutable router; IPoolManager public immutable poolManager; IPermit2 public immutable permit2; constructor(address _router, address _poolManager, address _permit2) { router = UniversalRouter(payable(_router)); poolManager = IPoolManager(_poolManager); permit2 = IPermit2(_permit2); } // We'll add more functions here } ``` -------------------------------- ### Install Dependencies Source: https://developers.uniswap.org/docs/community/tooling/v4-template After cloning the template repository, install the necessary Foundry dependencies using `forge install`. ```bash forge install ``` -------------------------------- ### Run Optional Checks and Start Local Node Source: https://developers.uniswap.org/docs/liquidity/liquidity-launchpad/guides/setup Install pre-commit hooks for automated checks before commits. Then, start a local Anvil node for local scripts and tests. ```bash pre-commit install pre-commit run --all-files ``` ```bash anvil ``` -------------------------------- ### Install the Graph CLI Source: https://developers.uniswap.org/docs/unichain/guides/subgraph-unichain Install the Graph CLI globally to manage subgraph development. ```bash npm install -g @graphprotocol/graph-cli ``` -------------------------------- ### Complete Swap Function Example Source: https://developers.uniswap.org/docs/protocols/v4/guides/swapping/routing A comprehensive example of a swap function that encodes commands, prepares parameters, executes the swap, and verifies the output. It includes deadline protection and ensures the minimum output amount is met. ```Solidity function swapExactInputSingle( PoolKey calldata key, uint128 amountIn, uint128 minAmountOut, uint256 deadline ) external returns (uint256 amountOut) { // Encode the Universal Router command bytes memory commands = abi.encodePacked(uint8(Commands.V4_SWAP)); bytes[] memory inputs = new bytes[](1); // Encode V4Router actions bytes memory actions = abi.encodePacked( uint8(Actions.SWAP_EXACT_IN_SINGLE), uint8(Actions.SETTLE_ALL), uint8(Actions.TAKE_ALL) ); // Prepare parameters for each action bytes[] memory params = new bytes[](3); params[0] = abi.encode( IV4Router.ExactInputSingleParams({ poolKey: key, zeroForOne: true, amountIn: amountIn, amountOutMinimum: minAmountOut, hookData: bytes("") }) ); params[1] = abi.encode(key.currency0, amountIn); params[2] = abi.encode(key.currency1, minAmountOut); // Combine actions and params into inputs inputs[0] = abi.encode(actions, params); // Execute the swap router.execute(commands, inputs, deadline); // Verify and return the output amount amountOut = IERC20(Currency.unwrap(key.currency1)).balanceOf(address(this)); require(amountOut >= minAmountOut, "Insufficient output amount"); return amountOut; } ``` -------------------------------- ### Install Solidity Dependencies for V4 Source: https://developers.uniswap.org/docs/get-started/quickstart Install the required smart contract packages for interacting with Uniswap V4 using Solidity. ```bash forge install uniswap/v4-core forge install uniswap/v4-periphery forge install uniswap/permit2 forge install uniswap/universal-router forge install OpenZeppelin/openzeppelin-contracts ``` -------------------------------- ### Install React SDK dependencies Source: https://developers.uniswap.org/docs/community/tooling/community-sdk Install the React SDK along with its peer dependencies. ```bash pnpm install @zahastudio/uniswap-sdk-react @zahastudio/uniswap-sdk viem wagmi @tanstack/react-query ``` -------------------------------- ### Install Swap Planner AI Skill Source: https://developers.uniswap.org/docs/api-reference/create_swap_transaction Install this AI skill for swap planning capabilities. It assists in planning swap transactions. ```bash npx skills add uniswap/uniswap-driver --skill swap-planner ``` -------------------------------- ### Complete Add/Remove Liquidity Workflow Example Source: https://developers.uniswap.org/docs/sdks/v4/guides/managing-liquidity/modifying-position Demonstrates a full workflow involving fetching position details, adding liquidity, waiting for verification, and then removing a specified percentage of liquidity. This example showcases the integration of adding and removing liquidity operations. ```typescript async function completeAddRemoveWorkflow() { const tokenId = 123456n // 1. Fetch position details const positionDetails = await getPositionDetails(tokenId) console.log(`Position: ${positionDetails.token0.symbol}/${positionDetails.token1.symbol}`) // 2. Add liquidity const addResult = await addLiquidityToPosition( positionDetails, '1000000000000000', // 0.001 ETH '1000000', // 1 USDC 0.05 // 5% slippage ) console.log(`Added liquidity: ${addResult.txHash}`) // 3. Wait and verify await new Promise((resolve) => setTimeout(resolve, 5000)) const updatedPosition = await getPositionDetails(tokenId) // 4. Remove 50% of liquidity const removeResult = await removeLiquidityFromPosition( updatedPosition, 0.5, // 50% 0.05, // 5% slippage false // don't burn token ) console.log(`Removed 50% liquidity: ${removeResult.txHash}`) return { addResult, removeResult } } ``` -------------------------------- ### Install Dependencies and Build CCA Source: https://developers.uniswap.org/docs/liquidity/liquidity-launchpad/guides/setup Install project dependencies and build the Continuous Clearing Auction project using Foundry's forge command. ```bash forge install forge build ``` -------------------------------- ### Install OpenZeppelin Hooks Library Source: https://developers.uniswap.org/docs/protocols/v4/guides/hooks/getting-started Install the OpenZeppelin Hooks library using Forge, the recommended package manager for Solidity projects. This library provides reference implementations for Uniswap v4 hooks. ```bash $ forge install OpenZeppelin/uniswap-hooks ``` -------------------------------- ### Full AccessSenderHook Contract Example Source: https://developers.uniswap.org/docs/protocols/v4/guides/hooks/accessing-msg.sender A complete Solidity contract example demonstrating the implementation of the `beforeSwap` hook to access the original `msg.sender`. Includes necessary imports and hook permissions. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {BaseHook} from "v4-periphery/src/utils/BaseHook.sol"; import {Hooks} from "v4-core/src/libraries/Hooks.sol"; import {IPoolManager} from "v4-core/src/interfaces/IPoolManager.sol"; import {SwapParams} from "v4-core/src/types/PoolOperation.sol"; import {PoolKey} from "v4-core/src/types/PoolKey.sol"; import {PoolId, PoolIdLibrary} from "v4-core/src/types/PoolId.sol"; import {BalanceDelta} from "v4-core/src/types/BalanceDelta.sol"; import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "v4-core/src/types/BeforeSwapDelta.sol"; import "forge-std/console.sol"; interface IMsgSender { function msgSender() external view returns (address); } contract AccessSenderHook is BaseHook { constructor(IPoolManager _poolManager) BaseHook(_poolManager) { } function _beforeSwap( address sender, PoolKey calldata, SwapParams calldata, bytes calldata ) internal override returns (bytes4, BeforeSwapDelta, uint24) { try IMsgSender(sender).msgSender() returns (address swapper) { console.log("Swap initiated by account:", swapper); } catch { revert("Router does not implement msgSender()"); } return (BaseHook.beforeSwap.selector, BeforeSwapDelta.wrap(0), 0); } function getHookPermissions( ) public pure override returns (Hooks.Permissions memory) { return Hooks.Permissions({ beforeInitialize: false, afterInitialize: false, beforeAddLiquidity: false, afterAddLiquidity: false, beforeRemoveLiquidity: false, afterRemoveLiquidity: false, beforeSwap: true, afterSwap: false, beforeDonate: false, afterDonate: false, beforeSwapReturnDelta: false, afterSwapReturnDelta: false, afterAddLiquidityReturnDelta: false, afterRemoveLiquidityReturnDelta: false }); } } ``` -------------------------------- ### Get Swappable Tokens Response Example Source: https://developers.uniswap.org/docs/api-reference/get_swappable_tokens This is an example of a successful response from the swappable_tokens endpoint. It includes a requestId and a list of swappable tokens with their details. ```json { "requestId": "", "tokens": [ { "address": "", "chainId": "", "name": "", "symbol": "", "project": { "logo": { "url": "" }, "safetyLevel": "", "isSpam": "" }, "isSpam": "", "decimals": "" } ] } ``` -------------------------------- ### Uniswap API - Get Quote Source: https://developers.uniswap.org/docs/get-started/quickstart Use the Uniswap API to integrate swapping quickly without implementing routing logic yourself. This example shows how to get a quote for a swap. ```APIDOC ## Uniswap API - Get Quote ### Description Use the Uniswap API to integrate swapping quickly without implementing routing logic yourself. Call `/quote` to get the most efficient route based on current inputs and expected output. ### Method `POST` ### Endpoint `https://trade-api.gateway.uniswap.org/v1/quote` ### Headers - `x-api-key`: YOUR_API_KEY - `Content-Type`: application/json - `Accept`: application/json ### Request Body - **tokenIn** (string) - Required - The address of the input token. - **tokenOut** (string) - Required - The address of the output token. - **amount** (string) - Required - The amount to swap (in wei for ETH, or smallest unit for ERC20). - **type** (string) - Required - Type of swap, e.g., `EXACT_INPUT`. - **tokenInChainId** (number) - Required - The chain ID for the input token. - **tokenOutChainId** (number) - Required - The chain ID for the output token. - **swapper** (string) - Required - The address of the user's wallet. - **slippageTolerance** (number) - Optional - The maximum acceptable slippage percentage. ### Request Example (cURL) ```bash curl --request POST \ --url https://trade-api.gateway.uniswap.org/v1/quote \ --header 'x-api-key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --data '{"tokenIn":"0x...","tokenOut":"0x...","amount":"1000000","type":"EXACT_INPUT","tokenInChainId":1,"tokenOutChainId":1,"swapper":"0x..."}' ``` ### Request Example (TypeScript) ```typescript const response = await fetch('https://trade-api.gateway.uniswap.org/v1/quote', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json', 'Accept': 'application/json', }, body: JSON.stringify({ tokenIn: '0x0000000000000000000000000000000000000000', // ETH tokenOut: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT tokenInChainId: 1, tokenOutChainId: 1, type: 'EXACT_INPUT', amount: '1000000000000000000', // 1 ETH in wei swapper: '0x...', // User wallet slippageTolerance: 0.5, // 0.5% }), }); const quote = await response.json(); ``` ### Response #### Success Response (200) - **routing** (string) - The routing information to be used for the execution request. - Other fields may be present depending on the quote details. ``` -------------------------------- ### Get Gasless Orders Response Example Source: https://developers.uniswap.org/docs/api-reference/get_order This is an example of a successful response when retrieving gasless orders. It includes details about the request ID and a list of orders matching the query parameters. ```json { "requestId": "", "orders": [ { "type": "", "encodedOrder": "", "signature": "", "nonce": "", "orderStatus": "", "orderId": "", "chainId": "", "quoteId": "", "swapper": "", "txHash": "", "input": { "token": "", "startAmount": "", "endAmount": "" }, "outputs": [ { "token": "", "startAmount": "", "endAmount": "", "isFeeOutput": "", "recipient": "" } ], "settledAmounts": [ { "tokenOut": "", "amountOut": "", "tokenIn": "", "amountIn": "" } ], "cosignature": "", "cosignerData": { "decayStartTime": "", "decayEndTime": "", "exclusiveFiller": "", "inputOverride": "", "outputOverrides": [ "" ] } } ], "cursor": "" } ``` -------------------------------- ### Get Swaps Status Response Example Source: https://developers.uniswap.org/docs/api-reference/get_swaps This is an example of a successful response (200 OK) from the swaps endpoint, showing the structure of the returned data including requestId and a list of swaps with their details. ```json { "requestId": "", "swaps": [ { "swapType": "", "status": "", "txHash": "", "swapId": "", "userOpHash": "", "hashType": "" } ] } ``` -------------------------------- ### Setting up StateView with Viem Source: https://developers.uniswap.org/docs/protocols/v4/guides/state-view Demonstrates how to connect to StateView using viem, a TypeScript library for Ethereum. Ensure stateViewABI is imported correctly. ```typescript import { createPublicClient, http } from 'viem'; import { mainnet } from 'viem/chains'; // Initialize the client const client = createPublicClient({ chain: mainnet, transport: http() }); // Set up StateView contract instance const stateView = getContract({ address: STATE_VIEW_ADDRESS, abi: stateViewABI, client }) ``` -------------------------------- ### Clone Tycho Simulation Repository Source: https://developers.uniswap.org/docs/unichain/guides/routing-on-unichain Clone the Tycho Simulation repository to access the quickstart code. This is the first step to begin trading on Unichain liquidity. ```bash git clone https://github.com/propeller-heads/tycho-simulation.git && cd tycho-simulation ``` -------------------------------- ### Basic Hook Setup with Fee Percentage Source: https://developers.uniswap.org/docs/protocols/v4/guides/custom-accounting Sets up a basic hook contract with a constant fee percentage and enables necessary permissions for swap operations. ```solidity // SPDX-License-Identifier: MIT pragma solidity 0.8.26; import {BaseHook} from "v4-periphery/src/utils/BaseHook.sol"; import {Hooks} from "v4-core/src/libraries/Hooks.sol"; import {IPoolManager} from "v4-core/src/interfaces/IPoolManager.sol"; import {SwapParams} from "v4-core/src/types/PoolOperation.sol"; import {PoolKey} from "v4-core/src/types/PoolKey.sol"; import {Currency} from "v4-core/src/types/Currency.sol"; import {BeforeSwapDelta, toBeforeSwapDelta} from "v4-core/src/types/BeforeSwapDelta.sol"; contract HookFeeExample is BaseHook { uint256 public constant HOOK_FEE_PERCENTAGE = 10;// 0.01% fee uint256 public constant FEE_DENOMINATOR = 100000; constructor(IPoolManager _poolManager) BaseHook(_poolManager) {} function getHookPermissions() public pure override returns (Hooks.Permissions memory) { return Hooks.Permissions({ beforeInitialize: false, afterInitialize: false, beforeAddLiquidity: false, beforeRemoveLiquidity: false, afterAddLiquidity: false, afterRemoveLiquidity: false, beforeSwap: true, afterSwap: false, beforeDonate: false, afterDonate: false, beforeSwapReturnDelta: true, afterSwapReturnDelta: false, afterAddLiquidityReturnDelta: false, afterRemoveLiquidityReturnDelta: false }); } } ``` -------------------------------- ### Permit2 Flow - Get Quote Source: https://developers.uniswap.org/docs/trading/swapping-api/integration-guide Example of how to fetch quote data, including permit information if required for the swap. ```APIDOC ## Permit2 Flow Permit2 is a token approval system which uses an offchain (gasless) EIP-712 signed message to allow an onchain contract to spend tokens from a wallet within pre-defined bounds. The API will return a `permitData` in the /quote response when one must be signed in order to perform the swap. The API will return `"permitData": null` in the /quote response when no permit needs to be signed. ### Implementation steps #### Get quote with permit data ```javascript const quoteResponse = await fetch('/quote', { method: 'POST', headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify({ tokenIn: '0x...', tokenOut: '0x...', amount: '1000000', type: 'EXACT_INPUT', swapper: '0x...', tokenInChainId: 1, tokenOutChainId: 1, permitAmount: 'FULL', // or 'EXACT' slippageTolerance: 0.5 }) }); const {quote, permitData, routing} = await quoteResponse.json(); ``` ``` -------------------------------- ### Test Points Awarded During Swap Source: https://developers.uniswap.org/docs/protocols/v4/guides/hooks/your-first-hook Tests the PointsHook's functionality by performing a swap and verifying that the correct amount of points are awarded. This snippet assumes the setup from the previous example has been completed. ```solidity function test_PointsHook_Swap() public { // We already have some points because we added some liquidity during setup. // So, we'll subtract those from the total points to get the points awarded for this swap. uint256 startingPoints = pointsToken.balanceOf(address(this)); // Let's swap some ETH for the token (single-pool swap on the v4 router; send ETH with the call). bool zeroForOne = true; int256 amountSpecified = -1e18; // negative number indicates exact input swap! swapRouter.swap{value: uint256(-amountSpecified)}({ amountSpecified: amountSpecified, amountLimit: 0, zeroForOne: zeroForOne, poolKey: key, hookData: hook.getHookData(address(this)), receiver: address(this), deadline: block.timestamp + 1 }); uint256 endingPoints = pointsToken.balanceOf(address(this)); // Let's make sure we got the right amount of points! assertEq( endingPoints - startingPoints, uint256(-amountSpecified), "Points awarded for swap should be 1:1 with ETH" ); } ``` -------------------------------- ### Install Foundry Source: https://developers.uniswap.org/docs/liquidity/liquidity-launchpad/guides/setup Install Foundry, a necessary tool for developing with CCA locally. This command downloads and installs the Foundryup installer. ```bash curl -L https://foundry.paradigm.xyz | bash ``` -------------------------------- ### Initialize Core SDK with viem Source: https://developers.uniswap.org/docs/community/tooling/community-sdk Create a public client with viem and initialize the Uniswap SDK with the client and chain ID. ```typescript import { createPublicClient, http } from "viem"; import { mainnet } from "viem/chains"; import { UniswapSDK } from "@zahastudio/uniswap-sdk"; const client = createPublicClient({ chain: mainnet, transport: http() }); const sdk = UniswapSDK.create(client, mainnet.id); ``` -------------------------------- ### Create Token Deployment Script Source: https://developers.uniswap.org/docs/unichain/guides/deploy-a-superchain-erc20 A Foundry script to deploy the ExampleToken contract with a deterministic address using a salt. ```solidity // SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\nimport {Script} from "forge-std/Script.sol";\nimport {console} from "forge-std/console.sol";\nimport {ExampleToken} from "../src/ExampleToken.sol";\n\ncontract Deploy is Script {\n function run() external {\n string memory saltStr = "{YOUR_SALT_HERE}";\n bytes32 salt = bytes32(abi.encodePacked(saltStr));\n\n vm.startBroadcast();\n // msg.sender here is the private key used to run the script\n // unichain sepolia chain id is 1301\n ExampleToken myToken = new ExampleToken{salt: salt}(msg.sender, 1301);\n console.log("Token deployed at:", address(myToken));\n\n vm.stopBroadcast();\n }\n} ``` -------------------------------- ### Verify Foundry Installation Source: https://developers.uniswap.org/docs/unichain/guides/deploy-a-smart-contract Verify the Foundry installation by checking its version. ```bash forge --version ``` -------------------------------- ### Initialize Universal Router and Permit2 Contracts Source: https://developers.uniswap.org/docs/sdks/v4/guides/swapping/multi-hop-swapping Set up the contract addresses and ABIs for the Universal Router and Permit2. These are required for interacting with the swap functionalities. ```javascript const UNIVERSAL_ROUTER_ADDRESS = "0x66a9893cC07D91D95644AEDD05D03f95e1dBA8Af" const PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3" // ABIs remain the same as in single-hop guide const UNIVERSAL_ROUTER_ABI = [/* ... */] const ERC20_ABI = [/* ... */] const PERMIT2_ABI = [/* ... */] ``` -------------------------------- ### Configure Project Remappings Source: https://developers.uniswap.org/docs/protocols/v4/guides/swapping/routing Set up remappings in `remappings.txt` to correctly alias the installed Uniswap and OpenZeppelin contract paths. ```plaintext @uniswap/v4-core/=lib/v4-core/ @uniswap/v4-periphery/=lib/v4-periphery/ @uniswap/permit2/=lib/permit2/ @uniswap/universal-router/=lib/universal-router/ @openzeppelin/contracts/=lib/openzeppelin-contracts/ ``` -------------------------------- ### Create Directory Structure Source: https://developers.uniswap.org/docs/unichain/guides/transfer-usdc Set up the required directory structure for the application's features, including wallet components and constants. ```bash app/ features/ wallet/ components/ WalletInterface.tsx constants/ contracts.ts hooks/ useWallets.ts ``` -------------------------------- ### Initialize Foundry Project Source: https://developers.uniswap.org/docs/protocols/v4/guides/managing-liquidity/getting-started Initialize a new Foundry project in the current directory. Use --force to overwrite existing files if necessary. ```bash forge init . --force ``` -------------------------------- ### Initialize Forge Project Source: https://developers.uniswap.org/docs/unichain/guides/deploy-a-superchain-erc20 Initializes a new project structure for smart contract development using Forge. ```bash forge init superchain_erc20 ``` -------------------------------- ### Install Uniswap v2 Dependencies Source: https://developers.uniswap.org/docs/unichain/guides/create-a-pool Install the necessary Uniswap v2 core and periphery libraries using forge. ```bash forge install uniswap/v2-core forge install uniswap/v2-periphery ``` -------------------------------- ### Install Uniswap v3 Dependencies Source: https://developers.uniswap.org/docs/unichain/guides/create-a-pool Install the necessary Uniswap v3 core and periphery libraries using forge. ```bash forge install uniswap/v3-core forge install uniswap/v3-periphery ``` -------------------------------- ### Install Uniswap v4 Dependencies with Foundry Source: https://developers.uniswap.org/docs/protocols/v4/guides/create-pool Install the v4-core and v4-periphery libraries using Foundry's package manager. ```bash forge install uniswap/v4-core forge install uniswap/v4-periphery ``` -------------------------------- ### Deploy Token Contract with Foundry Source: https://developers.uniswap.org/docs/unichain/guides/deploy-a-superchain-erc20 Executes the deployment script using Foundry to deploy the ExampleToken contract to the Unichain network. ```bash forge script script/Deploy.s.sol:Deploy \ --rpc-url unichain \ --private-key YOUR_PRIVATE_KEY \ --broadcast ``` -------------------------------- ### CREATE2 Proof Format Source: https://developers.uniswap.org/docs/protocols/the-compact/concepts/allocators When registering an allocator that will be deployed via CREATE2, format the proof as: 0xff ++ factory ++ salt ++ initcode hash. This enables pre-registration of deterministic addresses. ```solidity 0xff ++ factory ++ salt ++ initcode hash ``` -------------------------------- ### Navigate to Project Directory Source: https://developers.uniswap.org/docs/unichain/guides/deploy-a-smart-contract Navigate to your smart contract project's root directory before running Foundry commands. ```bash cd path/to/your/project ```