From 80454f012d1d6c9a79aed02ab95c8290c02ceaba Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Mon, 3 Feb 2025 10:55:37 +0000 Subject: [PATCH] feat: Add complex swap to quickstart example --- don't change below this line --- ENG-4087 Took 16 minutes --- examples/quickstart/main.rs | 126 +++++++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 25 deletions(-) diff --git a/examples/quickstart/main.rs b/examples/quickstart/main.rs index c68be70..5b46e1d 100644 --- a/examples/quickstart/main.rs +++ b/examples/quickstart/main.rs @@ -23,15 +23,71 @@ fn main() { EVMTychoEncoder::new(EVMStrategySelector, router_address, signer_pk, Chain::Ethereum) .expect("Failed to create encoder"); - // Prepare data to encode. We will encode a simple swap from WETH to DAI + // ------------------- Encode a simple swap ------------------- + + // Prepare data to encode. We will encode a simple swap from WETH to USDC // First we need to create a swap object let weth = Bytes::from_str("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2") .expect("Failed to create WETH address"); + let usdc = Bytes::from_str("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48") + .expect("Failed to create USDC address"); + + let simple_swap = Swap { + // The protocol component data comes from tycho-indexer + component: ProtocolComponent { + id: "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc".to_string(), + protocol_system: "uniswap_v2".to_string(), + ..Default::default() + }, + token_in: weth.clone(), + token_out: usdc.clone(), + // Split defines the fraction of the amount to be swapped. A value of 0 indicates 100% of + // the amount or the total remaining balance. + split: 0f64, + }; + + // Then we create a solution object with the previous swap + let solution = Solution { + sender: user_address.clone(), + receiver: user_address.clone(), + given_token: weth.clone(), + given_amount: BigUint::from_str("1_000000000000000000").expect("Failed to create amount"), + checked_token: usdc.clone(), + exact_out: false, // it's an exact in solution + check_amount: None, // the amount out will not be checked in execution + swaps: vec![simple_swap], + ..Default::default() + }; + + // Encode the solution + let tx = encoder + .encode_router_calldata(vec![solution.clone()]) + .expect("Failed to encode router calldata")[0] + .clone(); + println!(" ====== Simple swap WETH -> USDC ======"); + println!( + "The simple swap encoded transaction should be sent to address {:?} with the value of {:?} and the \ + following encoded data: {:?}", + tx.to, + tx.value, + hex::encode(tx.data) + ); + + // ------------------- Encode a swap with multiple splits ------------------- + // To illustrate a more complex solution, we will encode a swap from WETH to USDC with multiple + // splits. Performs a split swap from WETH to USDC though WBTC and DAI using USV2 pools + // + // ┌──(USV2)──> WBTC ───(USV2)──> USDC + // WETH ─┤ + // └──(USV2)──> DAI ───(USV2)──> USDC + // + + let wbtc = Bytes::from_str("0x2260fac5e5542a773aa44fbcfedf7c193bc2c599") + .expect("Failed to create WBTC address"); let dai = Bytes::from_str("0x6b175474e89094c44da98b954eedeac495271d0f") .expect("Failed to create DAI address"); - let swap = Swap { - // The protocol component data comes from tycho-indexer + let swap_weth_dai = Swap { component: ProtocolComponent { id: "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11".to_string(), protocol_system: "uniswap_v2".to_string(), @@ -39,35 +95,55 @@ fn main() { }, token_in: weth.clone(), token_out: dai.clone(), - // Split represents the percentage of the amount to be swapped. If it's 0 it represents 100% - // or what is left of the amount in. + split: 0.5f64, + }; + let swap_weth_wbtc = Swap { + component: ProtocolComponent { + id: "0xBb2b8038a1640196FbE3e38816F3e67Cba72D940".to_string(), + protocol_system: "uniswap_v2".to_string(), + ..Default::default() + }, + token_in: weth.clone(), + token_out: wbtc.clone(), + // This represents the remaining 50%, but to avoid any rounding errors we set this to + // 0 to signify "the remainder of the WETH value". It should still be very close to 50% split: 0f64, }; - - // Then we create a solution object with the previous swap - let solution = Solution { - sender: user_address.clone(), - receiver: user_address, - given_token: weth, - given_amount: BigUint::from_str("1_000000000000000000").expect("Failed to create amount"), - checked_token: dai, - exact_out: false, // it's an exact in solution - check_amount: None, // the amount out will not be checked in execution - swaps: vec![swap], - ..Default::default() + let swap_dai_usdc = Swap { + component: ProtocolComponent { + id: "0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5".to_string(), + protocol_system: "uniswap_v2".to_string(), + ..Default::default() + }, + token_in: dai.clone(), + token_out: usdc.clone(), + split: 0f64, }; + let swap_wbtc_usdc = Swap { + component: ProtocolComponent { + id: "0x004375Dff511095CC5A197A54140a24eFEF3A416".to_string(), + protocol_system: "uniswap_v2".to_string(), + ..Default::default() + }, + token_in: wbtc.clone(), + token_out: usdc.clone(), + split: 0f64, + }; + let mut complex_solution = solution.clone(); + complex_solution.swaps = vec![swap_weth_dai, swap_weth_wbtc, swap_dai_usdc, swap_wbtc_usdc]; // Encode the solution - let transactions = encoder - .encode_router_calldata(vec![solution]) - .expect("Failed to encode router calldata"); - let tx = transactions[0].clone(); + let complex_tx = encoder + .encode_router_calldata(vec![complex_solution]) + .expect("Failed to encode router calldata")[0] + .clone(); + println!(" ====== Complex split swap WETH -> USDC ======"); println!( - "The encoded transaction should be sent to address {:?} with the value of {:?} and the \ + "The complex solution encoded transaction should be sent to address {:?} with the value of {:?} and the \ following encoded data: {:?}", - tx.to, - tx.value, - hex::encode(tx.data) + complex_tx.to, + complex_tx.value, + hex::encode(complex_tx.data) ); }