UniswapSharp 2.0.1

dotnet add package UniswapSharp --version 2.0.1
                    
NuGet\Install-Package UniswapSharp -Version 2.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="UniswapSharp" Version="2.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="UniswapSharp" Version="2.0.1" />
                    
Directory.Packages.props
<PackageReference Include="UniswapSharp" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add UniswapSharp --version 2.0.1
                    
#r "nuget: UniswapSharp, 2.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package UniswapSharp@2.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=UniswapSharp&version=2.0.1
                    
Install as a Cake Addin
#tool nuget:?package=UniswapSharp&version=2.0.1
                    
Install as a Cake Tool

<p align="center"> <img src="https://raw.githubusercontent.com/grinidx/UniswapSharp/main/assets/logo.png" alt="UniswapSharp" width="128" height="128"> </p>

<h1 align="center">UniswapSharp</h1>

<p align="center"> <strong>The Uniswap SDK for .NET.</strong><br> A faithful C# port of the official <a href="https://github.com/Uniswap/sdks"><code>Uniswap/sdks</code></a> monorepo — verified to the digit against upstream's own test vectors. </p>

<p align="center"> <a href="https://www.nuget.org/packages/UniswapSharp"><img alt="NuGet" src="https://img.shields.io/nuget/v/UniswapSharp.svg?logo=nuget"></a> <a href="https://www.nuget.org/packages/UniswapSharp"><img alt="Downloads" src="https://img.shields.io/nuget/dt/UniswapSharp.svg?logo=nuget"></a> <a href="https://github.com/grinidx/UniswapSharp/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/grinidx/UniswapSharp/actions/workflows/ci.yml/badge.svg"></a> <a href="https://github.com/grinidx/UniswapSharp/actions/workflows/codeql.yml"><img alt="CodeQL" src="https://github.com/grinidx/UniswapSharp/actions/workflows/codeql.yml/badge.svg"></a> <img alt=".NET" src="https://img.shields.io/badge/.NET-10.0-512BD4?logo=dotnet&logoColor=white"> <a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-blue.svg"></a> </p>

<p align="center"> <a href="#install">Install</a> · <a href="#quickstart">Quickstart</a> · <a href="#examples">Examples</a> · <a href="#whats-in-the-box">What's in the box</a> · <a href="#design-notes">Design notes</a> · <a href="docs/PORTING.md">Porting guide</a> · <a href="CHANGELOG.md">Changelog</a> </p>


Model currencies, tokens, pools, positions, routes and trades. Run the tick, sqrt-price, swap and liquidity math. Build calldata for the V3/V4 periphery and the Universal Router. Hash and sign Permit2 permits and UniswapX orders.

All of it offline and deterministic — no RPC required, and no floating point anywhere in protocol math (exact BigInteger / BigRational throughout).

Namespaces and file names deliberately mirror the upstream TypeScript, so the two read side by side.

v2.0.0 · 1,920 tests, 0 failing on Linux / Windows / macOS, zero compiler warnings · at upstream parity with Uniswap/sdks@35c4e35 (2026-09-01). Upgrading from 1.x? See Migrating from 1.0.0 — two call sites move.

Install

dotnet add package UniswapSharp

Targets .NET 10 (net10.0). One package, no plugins — every namespace below ships in it.

Quickstart

using System.Numerics;
using UniswapSharp.Core.Entities;
using UniswapSharp.V3.Entities;
using UniswapSharp.V3.Utils;
using FeeAmount = UniswapSharp.V3.Constants.FeeAmount;

var usdc = new Token(1, "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", 6, "USDC", "USD Coin");
var weth = new Token(1, "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", 18, "WETH", "Wrapped Ether");

// Deterministic V3 pool address — CREATE2, no network call.
Console.WriteLine(Pool.GetAddress(usdc, weth, FeeAmount.MEDIUM));

// Construct a pool at ~2000 USDC per WETH and read the price back.
var sqrtPriceX96 = EncodeSqrtRatioX96.Encode(
    BigInteger.Parse("1000000000000000000000"),   // 1,000 WETH
    BigInteger.Parse("2000000000000"));           // 2,000,000 USDC
var pool = new Pool(usdc, weth, FeeAmount.MEDIUM, sqrtPriceX96,
    BigInteger.Zero, TickMath.GetTickAtSqrtRatio(sqrtPriceX96));

Console.WriteLine($"1 WETH = {pool.PriceOf(weth).ToSignificant(6)} USDC");
0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8
1 WETH = 2000 USDC

Examples

<details open> <summary><strong>Build swap calldata for the V3 router</strong></summary>

Quote a trade and produce a signable transaction. A pool needs tick data to be swapped against offline — here a single full-range position stands in for the real tick list you'd load from a subgraph or TickLens.

using System.Numerics;
using UniswapSharp.Core;
using UniswapSharp.Core.Entities;
using UniswapSharp.Core.Entities.Fractions;
using UniswapSharp.V3;
using UniswapSharp.V3.Entities;
using UniswapSharp.V3.Utils;
using FeeAmount = UniswapSharp.V3.Constants.FeeAmount;

var usdc = new Token(1, "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", 6, "USDC", "USD Coin");
var weth = new Token(1, "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", 18, "WETH", "Wrapped Ether");

var sqrtPriceX96 = EncodeSqrtRatioX96.Encode(
    BigInteger.Parse("1000000000000000000000"), BigInteger.Parse("2000000000000"));
var liquidity = BigInteger.Parse("100000000000000000000");
int spacing = UniswapSharp.V3.Constants.TICK_SPACINGS[FeeAmount.MEDIUM];

var ticks = new List<Tick>
{
    new(NearestUsableTick.Find(TickMath.MIN_TICK, spacing), liquidity, liquidity),
    new(NearestUsableTick.Find(TickMath.MAX_TICK, spacing), -liquidity, liquidity),
};

var pool = new Pool(usdc, weth, FeeAmount.MEDIUM, sqrtPriceX96, liquidity,
    TickMath.GetTickAtSqrtRatio(sqrtPriceX96), ticks);

var trade = await Trade<Token, Token>.FromRoute(
    new Route<Token, Token>([pool], usdc, weth),
    CurrencyAmount<Token>.FromRawAmount(usdc, 1_000_000_000),   // exactly 1,000 USDC
    TradeType.EXACT_INPUT);

var slippage = new Percent(50, 10_000);   // 0.50%
var parameters = SwapRouter.SwapCallParameters(trade, new Staker.SwapOptions
{
    SlippageTolerance = slippage,
    Recipient = "0x0000000000000000000000000000000000000003",
    Deadline   = 2_000_000_000,
});

Console.WriteLine($"quoted out   : {trade.OutputAmount.ToSignificant(6)} WETH");
Console.WriteLine($"min out      : {trade.MinimumAmountOut(slippage).ToSignificant(6)} WETH");
Console.WriteLine($"price impact : {trade.PriceImpact.ToSignificant(3)}%");
Console.WriteLine($"selector     : {parameters.Calldata[..10]}");   // exactInputSingle
quoted out   : 0.498499 WETH
min out      : 0.496019 WETH
price impact : 0.3%
selector     : 0x414bf389

parameters.Calldata and parameters.Value go straight into an eth_sendTransaction. </details>

<details> <summary><strong>Sign a Permit2 permit</strong></summary>

using UniswapSharp.Permit2;

var permit = new PermitTransferFrom(
    Permitted: new TokenPermissions("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", 1_000_000_000),
    Spender:   "0x0000000000000000000000000000000000000003",
    Nonce:     0,
    Deadline:  2_000_000_000);

const string permit2 = "0x000000000022D473030F116dDEE9F6B43aC78BA3";

// The EIP-712 digest a wallet signs.
Console.WriteLine(SignatureTransfer.Hash(permit, permit2, chainId: 1));

// Or the full typed-data payload, for eth_signTypedData_v4.
PermitData data = SignatureTransfer.GetPermitData(permit, permit2, chainId: 1);
0x4d55f96e4cee5574a9b358c7ec7378b3b21a27b94c5979fced600845ac5e8d12

The typed-data encoder is a byte-exact port of ethers' _TypedDataEncoder, pinned against upstream's EIP-712 hash vectors. </details>

<details> <summary><strong>More</strong></summary>

The test suite under test/UniswapSharp.Testing/ mirrors the source tree and doubles as a worked example library — every case is a round-trip against an upstream vector. Good entry points:

I want to… Look at
Build V3 swap calldata V3/SwapRouterTests.cs, V3/SwapRouterMultiTests.cs
Mint / manage a V3 position V3/NonfungiblePositionManagerTests.cs
Work with V4 pools and hooks V4/Entities/PoolTests.cs, V4/Utils/HookTests.cs
Plan a V4 action sequence V4/Utils/V4PlannerTests.cs, V4/PositionManagerTests.cs
Route across v2 + v3 + v4 Router/Entities/MixedRoute/MixedRouteTests.cs
Drive the Universal Router UniversalRouter/EncodeSwapsTests.cs, UniversalRouter/RouterTradeAdapterTests.cs
Build and hash a UniswapX order UniswapX/DutchOrderTests.cs, UniswapX/OrderUtilsTests.cs
Sign Permit2 Permit2/SignatureTransferTests.cs, Permit2/AllowanceTransferTests.cs
Launch a token LiquidityLauncher/QuickLaunchTests.cs, LiquidityLauncher/InstantLaunchTests.cs

</details>

What's in the box

Every namespace maps one-to-one to an upstream package.

Namespace Upstream package What's in it
UniswapSharp.Core @uniswap/sdk-core Token, Ether, Fraction/Percent/Price/CurrencyAmount, chain + address registries, WETH9
UniswapSharp.V2 @uniswap/v2-sdk Pair (CREATE2 + 997/1000 fee math), Route, Trade, Router
UniswapSharp.V3 @uniswap/v3-sdk Pool, Position, Route, Trade, Tick; tick / sqrt-price / swap / liquidity math; periphery calldata
UniswapSharp.V4 @uniswap/v4-sdk currency-based Pool/Position/Route/Trade, hook permissions, V4Planner, PositionManager
UniswapSharp.Router @uniswap/router-sdk mixed v2+v3+v4 routes, aggregated Trade, SwapRouter02 calldata
UniswapSharp.UniversalRouter @uniswap/universal-router-sdk RoutePlanner, RouterTradeAdapter, SwapRouter, direct transfers, signed-route EIP-712
UniswapSharp.UniswapX @uniswap/uniswapx-sdk Dutch / Priority / Relay / V3 / Hybrid orders, decay math, builders, trades, Permit2-witness hashing
UniswapSharp.Permit2 @uniswap/permit2-sdk SignatureTransfer, AllowanceTransfer, byte-exact EIP-712 typed-data encoder
UniswapSharp.SmartWallet @uniswap/smart-wallet-sdk ERC-7821 call planners and encoders
UniswapSharp.LiquidityLauncher @uniswap/liquidity-launcher-sdk launch config math, CREATE2 poolId / salts, quick-launch and instant-launch surfaces
UniswapSharp.Flashtestations @uniswap/flashtestations-sdk TEE workload ID (keccak) + block verification, injectable RPC
UniswapSharp.Tamperproof @uniswap/tamperproof-transactions EIP-7754 sign / verify (RSA, ECDSA, Ed25519), canonical JSON, injectable DNS-over-HTTPS

Design notes

Exact arithmetic, always. Protocol math runs on System.Numerics.BigInteger and BigRational. There is no double or decimal anywhere a price, tick, or amount is computed — rounding and tick boundaries agree with upstream to the last digit.

Verified against upstream, not against ourselves. Every ported module brings its upstream .test.ts cases across as xUnit tests. Where upstream ships golden calldata, addresses, or EIP-712 digests, those are pinned verbatim — including on-chain-observed values such as launcher dispatcher selectors and real pool ids.

Offline and deterministic. The library builds calldata and computes math; it never opens a socket. The few upstream modules that genuinely need a live node (quoters, validators, event watchers) sit behind injectable interfaces or are deliberately out of scope — docs/PORTING.md lists every one and why.

Nullable-clean. Nullable reference types are enabled and the solution builds with zero warnings. Option and parameter types carry explicit null contracts derived from the upstream TypeScript interfaces.

Versioning

Semantic Versioning. The public API surface, the calldata a given input produces, and the numeric output of protocol math are all covered — a change to any of them that would alter a caller's bytes or numbers is a major.

Releases are tagged v* and published to NuGet from CI via Trusted Publishing (OIDC, keyless — no long-lived API key exists). Packages ship with SourceLink and symbols, so you can step into the source from your debugger.

Building from source

git clone https://github.com/grinidx/UniswapSharp.git
cd UniswapSharp
dotnet build -c Release
dotnet test  -c Release

Requires the .NET 10 SDK. Tests run on Microsoft.Testing.Platform (selected by global.json); CI runs the full suite on ubuntu, windows and macOS, plus CodeQL.

Contributing

Contributions are welcome — see CONTRIBUTING.md. The short version: work test-first, port the upstream .test.ts cases alongside the code, match upstream to the digit, and land everything through a PR with green CI.

docs/PORTING.md is the map: the file-by-file correspondence to upstream, the re-sync workflow, and every intentional divergence.

Please also read the Code of Conduct and the Security Policy.

License and attribution

MIT — see LICENSE.

UniswapSharp is a derivative work of the MIT-licensed Uniswap/sdks (© Uniswap Labs). It is an independent port and is not affiliated with, endorsed by, or supported by Uniswap Labs.

This software is provided as is, without warranty. It constructs transaction calldata that moves real funds. Verify calldata, amounts and slippage independently — ideally by simulating against a fork — before broadcasting anything on-chain.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.1 74 9/6/2026
2.0.0 73 9/4/2026
1.0.0 146 7/13/2026
1.0.0-rc.2 71 7/13/2026
1.0.0-rc.1 65 7/12/2026