Skip to content

Latest commit

 

History

History
138 lines (95 loc) · 6.13 KB

L4.2_PriceView.md

File metadata and controls

138 lines (95 loc) · 6.13 KB

🏷 PriceView

In this lesson, we will surface the amount of buy token a user can swap when they input a sell amount.

We will need to complete the following:

  • plug the /price endpoint into our PriceView
  • automatically fetch a new price whenever the inputs change (e.g. new sell amount, new sell token selected)
  • format the user inputted amounts so the API can read it, and format response from the API so it is human-readable

What is it?

PriceView is the component where users can browse for a price without committing to a trade, aka, get the indicative price. Recall that an indicative price is used when users just want to check the price they could receive on a trade, for this we will use the /swap/v1/price endpoint.

Currently, when a user inputs a sellAmount, the corresponding amount they can buy doesn't automatically appear in the UI. We want the buyAmount to populate with the price we get from /swap/v1/price.

Fetch price from PriceView

In the previous lesson, we saw how to fetch a price using /price. Now we need to plug it into the UI.

Step 1. Wrap price API request

To do this in Next, we will need to wrap our API request is wrapped behind /app/api/price/route.ts using Next.js Route Handlers.

Why wrap? To protect our API keys.

Wrapping our API key protects it because all API requests are viewable by if someone inspects the browser, but we don’t want them inspecting an finding our keys. Instead, when the user queries for an indicative price, it pings our API setup in /app/api/price/route.ts and that pings the 0x Swap API using the API key in the header.

// Create /app/api/price/route.ts and add this code

import { type  NextRequest } from  "next/server";



export  async  function  GET(request:  NextRequest) {
	const  searchParams  =  request.nextUrl.searchParams;



	try {

		const  res  =  await  fetch(
	`https://polygon.api.0x.org/swap/v1/swap/price?${searchParams}`,
		{
			headers: {
				"0x-api-key":  process.env.NEXT_PUBLIC_ZEROEX_API_KEY  as  string,
		},
	  }
	);
	const  data  =  await  res.json();
	return  Response.json(data);
	} catch (error) {
	console.log(error);
	}
}

Step 2. Automatically fetch price with useEffect hook

Now we need to hook it up to the front-end and trigger a price change anytime the sellAmount updates.

In PriceView, we use the Next.js App Router's built-in data fetching pattern and the useEffect hook to fetch a price and automatically update the UI will quickly to respond to any changes, such as when the user inputs a new sellAmount.

The code will look something like this. Essentially we ask useEffect to monitor a list of params (sellToken, buyToken, etc), and if ever any of these params change value, then the main() function is executed. In this function, we fetch a new /price with the updated param values.

// Fetch price data and set the buyAmount whenever the sellAmount changes

useEffect(() => {
	const params = {
	sellToken: sellTokenObject.address,
	buyToken: buyTokenObject.address,
	sellAmount: parsedSellAmount,
	buyAmount: parsedBuyAmount,
	takerAddress,
	};
	
	async function main() {
	const response = await fetch(`/api/price?${qs.stringify(params)}`);
	const data = await response.json();
	
	if (data?.validationErrors?.length > 0) {
	// error for sellAmount too low
	setError(data.validationErrors);
	} else {
	setError([]);
	}
	if (data.buyAmount) {
	setBuyAmount(formatUnits(data.buyAmount, 18));
	setPrice(data);
	}
	}
	
	if (sellAmount !== "") {
	main();
	}
	}, [
	sellTokenObject.address,
	buyTokenObject.address,
	parsedSellAmount,
	parsedBuyAmount,
	takerAddress,
	sellAmount,
	setPrice,
	]);

Some additional house keeping that needs to be set up include:

  • setup PriceResponse type in /src/utils/types
  • import qs , a library for parsing and string-ifying query strings or URL query parameters in /app/components/price.tsx
  • optional, console.log to see the the price object that is returned by the API. See screenshot below: Screenshot 2024-04-10 at 2 59 40 PM

Note: When testing out the API call, you likely need to input a very large number (e.g. 10 ^ 18) depeding on the decimal representation of the ERC20 token. In the next section, we will learn how to format the inputs and outputs to be API-reable and human-readable, respectively.

Format and Parse sellAmount and buyAmount

Recall that the inputted sellAmount and buyAmounts each have their own decimal values. We will need to parse the number that the user inputs to be usable for the API request as well as format the number that is returned by the API request to be easily human readable. To do so, we will use the following methods from ethers.js:

  • parseUnits - Parses a string representing ether, such as the string 1.1 into a BigNumber in wei. This is useful to convert a user inputted value into a BigNumber that is usable for API requests.
  • formatUnits - This one does the opposite of parseUnits. It formats a BigNumberish into a string, which is useful when displaying a balance or displaying a BigNumerish value returned from an API response as a string in the UI.

Summary

Fetch /swap/v1/swap/price is wrapped behind app/api/price/route.ts and triggered in the UI by useEffect in /app/components/price.tsx

Your app should now look like this:

Screenshot 2024-04-16 at 4 59 06 PM

See the final code for this lesson here:

https://github.com/0xProject/token-swap-dapp-course-code/tree/main/L4