UniswapKit.Swift extends EvmKit.Swift to support Uniswap DEX and some other DEXes using the same smart contract codebase. Currently, UnstoppableWallet uses this kit for integration of Uniswap(Ethereum), PancakeSwap(BSC), QuickSwap(Polygon) and Trader Joe(Avalanche)
- ExactIn/ExactOut trades
- Price Impact/Deadline/Recipient options
- Fee on Transfer
import EvmKit
import UniswapKit
let evmKit = try Kit.instance(
address: try EvmKit.Address(hex: "0x..user..address.."),
chain: .ethereum,
rpcSource: .ethereumInfuraWebsocket(projectId: "...", projectSecret: "..."),
transactionSource: .ethereumEtherscan(apiKey: "..."),
walletId: "unique_wallet_id",
minLogLevel: .error
)
let uniswapKit = UniswapKit.Kit.instance(evmKit: evmKit)
// Decorators are needed to detect and decorate transactions as `Uniswap` transactions
UniswapKit.Kit.addDecorators(to: evmKit)// Get Signer object
let seed = Mnemonic.seed(mnemonic: ["mnemonic", "words", ...])!
let signer = try Signer.instance(seed: seed, chain: .ethereum)
// Sample swap data
let tokenIn = uniswapKit.etherToken
let tokenOut = uniswapKit.token(contractAddress: try! EvmKit.Address(hex: "0x..token..address"), decimals: 18)
let amount: Decimal = 0.1
let gasPrice = GasPrice.legacy(gasPrice: 50_000_000_000)
// Get SwapData. SwapData is a list of pairs available in Uniswap smart contract at the moment
let transactionDataSingle: Single<TransactionData> = uniswapKit.swapDataSingle(tokenIn: tokenIn, tokenOut: tokenOut)
.map { swapData in
// Get TradeData. TradeData is the best swap route evaluated by UniswapKit
let tradeData = try! uniswapKit.bestTradeExactIn(swapData: swapData, amountIn: amount)
// Convert TradeData to EvmKit TransactionData
return try! uniswapKit.transactionData(tradeData: tradeData)
}
// Estimate gas for the transaction
let estimateGasSingle = transactionDataSingle.flatMap { transactionData in
evmKit.estimateGas(transactionData: transactionData, gasPrice: gasPrice)
}
// Generate a raw transaction which is ready to be signed. This step also synchronizes the nonce
let rawTransactionSingle = estimateGasSingle.flatMap { estimatedGasLimit in
evmKit.rawTransaction(transactionData: transactionData, gasPrice: gasPrice, gasLimit: estimatedGasLimit)
}
let sendSingle = rawTransactionSingle.flatMap { rawTransaction in
// Sign the transaction
let signature = try signer.signature(rawTransaction: rawTransaction)
// Send the transaction to RPC node
return evmKit.sendSingle(rawTransaction: rawTransaction, signature: signature)
}
let disposeBag = DisposeBag()
sendSingle
.subscribe(
onSuccess: { fullTransaction in
let transaction = fullTransaction.transaction
print("Transaction sent: \(transaction.hash.hs.hexString)")
}, onError: { error in
print("Send failed: \(error)")
}
)
.disposed(by: disposeBag)With UniswapKit you can build swap transaction that either has an exact In or exact Out amount. That is, if you want to swap exactly 1 ETH to USDT, you get TradeData using bestTradeExactIn method. Similarly, if you want to swap ETH to USDT and you want to get exactly 1000 USDT, then you get TradeData using bestTradeExactOut
UniswapKit supports Price Impact/Deadline/Recipient options. You can set them in TradeOptions object passed to bestTradeExactIn/bestTradeExactOut methods. Please, look at official Uniswap app documentation to learn about those options.
dependencies: [
.package(url: "https://github.com/horizontalsystems/UniswapKit.Swift.git", .upToNextMajor(from: "1.0.0"))
]The UniswapKit.Swift toolkit is open source and available under the terms of the MIT License.