Skip to content

Commit

Permalink
swap-pricing functionality added
Browse files Browse the repository at this point in the history
  • Loading branch information
anshuman008 committed Oct 6, 2024
1 parent 01b28d2 commit c386d74
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 58 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"react": "^18",
"react-dom": "^18",
"react-icons": "^5.2.1",
"react-loader-spinner": "^6.1.6",
"react-wrap-balancer": "^1.1.1",
"shamir-secret-sharing": "^0.0.3",
"tailwind-merge": "^2.4.0"
Expand Down
156 changes: 101 additions & 55 deletions src/components/WalletPage/Swap.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,70 @@
"use client"
import { useState, useEffect } from "react";
import { ArrowUpDown, ChevronDown, Space } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import axios from "axios";
import Image from "next/image";
import { tokens, TokensType } from "./token";
import { ActionType } from "./actions";
import { SUPPORTED_TOKENS } from "@/lib/token";
import { RotatingLines, ThreeDots } from 'react-loader-spinner'

import { useState } from "react"
import { ArrowUpDown, ChevronDown, Space } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { ActionType } from "./actions"
import {tokens,TokensType}from "./token"
interface TokenSwapProps {
setCurrent: (action: ActionType | null) => void;
}

import Image from "next/image"
export default function TokenSwap({ setCurrent }: TokenSwapProps) {
const [payToken, setPayToken] = useState(tokens[0]);
const [receiveToken, setReceiveToken] = useState(tokens[1]);
const [payAmount, setPayAmount] = useState("");
const [receiveAmount, setReceiveAmount] = useState("");
const [fetchingQuote, setFetchingQuote] = useState(false)

interface TokenSwapProps {
setCurrent: (action: ActionType | null) => void;
}
;

useEffect(() => {
if (!payAmount || !/^\d*\.?\d*$/.test(payAmount)) {
setReceiveAmount("");
return;
}
setFetchingQuote(true);

const fetchQuote = async () => {
try {
const res = await axios.get(`https://quote-api.jup.ag/v6/quote?inputMint=${payToken.mint}&outputMint=${receiveToken.mint}&amount=${Number(payAmount) * (10 ** payToken.decimals)}&slippageBps=50`)

const outputAmount = Number(res.data.outAmount) / 10 ** receiveToken.decimals;
setReceiveAmount(outputAmount.toString());
} catch (error) {
console.error("Error fetching swap price:", error);
setReceiveAmount("");
} finally {
setFetchingQuote(false);
}
};

export default function TokenSwap({setCurrent}:TokenSwapProps) {
const [payToken, setPayToken] = useState(tokens[0])
const [receiveToken, setReceiveToken] = useState(tokens[1])
const [payAmount, setPayAmount] = useState("")
const [receiveAmount, setReceiveAmount] = useState("")
const debounceFetch = setTimeout(fetchQuote, 500); // Debounce for 500ms
return () => clearTimeout(debounceFetch); // Clean up previous timeout if the amount changes
}, [payAmount, payToken, receiveToken]);

const handleSwap = () => {
setPayToken(receiveToken)
setReceiveToken(payToken)
setPayAmount(receiveAmount)
setReceiveAmount(payAmount)
}
setPayToken(receiveToken);
setReceiveToken(payToken);
setPayAmount(receiveAmount);
setReceiveAmount(payAmount);
};

useEffect(() => {
console.log('i have this: ', payToken, 'i want this: ', receiveToken)
}, [payToken, receiveToken])

return (
<div className="w-full max-w-md mx-auto p-6 space-y-6 bg-white rounded-lg">
<div className="flex justify-between items-center">
<button className="text-sm font-medium text-gray-500" onClick={() => setCurrent(null)}>← Back</button>
<button className="text-sm font-medium text-gray-500" onClick={() => setCurrent(null)}>
← Back
</button>
<h2 className="text-2xl font-bold">Swap Tokens</h2>
<div className="w-10" />
</div>
Expand All @@ -41,9 +75,9 @@ export default function TokenSwap({setCurrent}:TokenSwapProps) {
<div className="flex items-center space-x-2">
<Select
value={payToken.symbol}
onValueChange={(value:TokensType) => {
const newToken = tokens.find((t) => t.symbol === value)
if (newToken && newToken !== receiveToken) setPayToken(newToken)
onValueChange={(value: TokensType) => {
const newToken = tokens.find((t) => t.symbol === value);
if (newToken && newToken !== receiveToken) setPayToken(newToken);
}}
>
<SelectTrigger className="w-[250px]">
Expand All @@ -65,12 +99,11 @@ export default function TokenSwap({setCurrent}:TokenSwapProps) {
type="text"
placeholder="0.00"
value={payAmount}
onChange={(e) =>{

if(/^\d*\.?\d*$/.test(e.target.value)){
setPayAmount(e.target.value)
}
} }
onChange={(e) => {
if (/^\d*\.?\d*$/.test(e.target.value)) {
setPayAmount(e.target.value);
}
}}
className="flex-grow text-right"
/>
</div>
Expand All @@ -88,9 +121,9 @@ export default function TokenSwap({setCurrent}:TokenSwapProps) {
<div className="flex items-center space-x-2">
<Select
value={receiveToken.symbol}
onValueChange={(value:TokensType) => {
const newToken = tokens.find((t) => t.symbol === value)
if (newToken && newToken !== payToken) setReceiveToken(newToken)
onValueChange={(value: TokensType) => {
const newToken = tokens.find((t) => t.symbol === value);
if (newToken && newToken !== payToken) setReceiveToken(newToken);
}}
>
<SelectTrigger className="w-[250px]">
Expand All @@ -107,31 +140,44 @@ export default function TokenSwap({setCurrent}:TokenSwapProps) {
))}
</SelectContent>
</Select>
<Input
type="number"
placeholder="0.00"
value={receiveAmount}
onChange={(e) => setReceiveAmount(e.target.value)}
className="flex-grow text-right"
readOnly
/>
<div className="border-2 w-full rounded-lg h-10 flex justify-center items-center">

{
!fetchingQuote && <Input
type="text"
placeholder="0.00"
value={receiveAmount}
className="flex-grow text-right"
readOnly
/>
}

<span className="">
{fetchingQuote && (
<ThreeDots
visible={true}
height="30"
width="30"
color="#A9A9A9"
radius="9"
ariaLabel="three-dots-loading"
wrapperStyle={{}}
wrapperClass=""
/>
)}
</span>
</div>

</div>
<p className="text-sm text-gray-500 mt-1">Current Balance: 0 {receiveToken.symbol}</p>
</div>
</div>

<div className="space-y-2">
<span className="w-full text-xs cursor-pointer flex gap-x-1 items-center" >
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-4">
<path strokeLinecap="round" strokeLinejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" />
</svg>



<span> View Swap Details</span>
</span>
<Button className="w-full">Confirm & Swap</Button>
<Button className="w-full" disabled={fetchingQuote || !receiveAmount}>
{fetchingQuote ? "Fetching Price..." : "Confirm & Swap"}
</Button>
</div>
</div>
)
}
);
}
2 changes: 1 addition & 1 deletion src/components/WalletPage/WalletDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const WalletDetail = ({ wallet, balance }: WalletDetailProps) => {


return (
<div className="flex flex-col items-center gap-3 border-2 sm:p-10 shadow-md mb-16 w-full max-w-md mx-auto p-6 space-y-6 bg-white rounded-lg">
<div className="flex flex-col items-center gap-3 border-2 sm:p-10 shadow-md mb-16 w-full max-w-md mx-auto space-y-6 bg-white rounded-lg">
<div className="flex flex-col items-start gap-2 w-full">
<div className="text-gray-200">
<p className="text-gray-400 text-xs sm:text-sm font-semibold">
Expand Down
16 changes: 14 additions & 2 deletions src/components/WalletPage/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,20 @@ import solanaIcon from "../icons/solana.png";
import usdcIcon from "../icons/usdc.png";

export const tokens = [
{ symbol: "SOL", name: "Solana", icon: solanaIcon },
{ symbol: "USDC", name: "USD", icon: usdcIcon },
{ symbol: "SOL", name: "Solana", icon: solanaIcon,
mint: "So11111111111111111111111111111111111111112",
native: true,
price: "180",
image: "https://upload.wikimedia.org/wikipedia/commons/3/34/Solana_cryptocurrency_two.jpg",
decimals: 9
},
{ symbol: "USDC", name: "USDC", icon: usdcIcon,
mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
native: false,
price: "1",
image: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT1vAKYEl0YffTpWSxrqEi_gmUsl-0BuXSKMQ&s",
decimals: 6
},
]

export type TokensType = typeof tokens[number]['symbol'];

0 comments on commit c386d74

Please sign in to comment.