-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathBuyWithLeverageSection.tsx
More file actions
126 lines (118 loc) · 5.24 KB
/
Copy pathBuyWithLeverageSection.tsx
File metadata and controls
126 lines (118 loc) · 5.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import { BuyWithLeverage, BWLToken, useDeployment } from "@metastreet-labs/margin-kit";
import { useState } from "react";
import { useAccount, useNetwork } from "wagmi";
import Button from "./Button";
import Input from "./Input";
const BuyWithLeverageSection = () => {
// active chain ID and address, used to construct a call for action link
const chainID = useNetwork().chain?.id ?? 1;
const { address = "" } = useAccount();
// deployment object, grabbed from the DeploymentProvider that wraps the app
const deployment = useDeployment();
// value of the collection address input, defaults to Goerli's MultiFaucet NFT
const [collectionAddress, setCollectionAddress] = useState("0xf5de760f2e916647fd766b4ad9e85ff943ce3a2b");
// value of the token IDs input, defaults to 3 random token IDs
const [tokenIDs, setTokenIDs] = useState("958576,1390026,940282");
// the fetched tokens
const [tokens, setTokens] = useState<BWLToken[]>([]);
// construct a call for action link, it will be shown on modal success
const tradesDashboardLink =
chainID == 1 ? "https://powersweep.metastreet.xyz/" : "https://powersweep-goerli.metastreet.xyz/";
const callForActionLink = `${tradesDashboardLink}/address/${address}?tab=trades`;
// called when the fetch button is clicked
// it fetches NFT objects based on the entered collection address and token IDs
const fetchToken = async () => {
// if deployment is undefined, either it's an unsupported network,
// or there was no DeploymentProvider up the component tree
if (!deployment) throw new Error("Deployment is undefined (unsupported network)");
// construct query params
const params = new URLSearchParams();
const tokenIDsArray = tokenIDs.split(",");
tokenIDsArray.forEach((id) => params.append("tokens", `${collectionAddress}:${id}`));
// make the call to reservoir API, we use this endpoint: https://docs.reservoir.tools/reference/gettokensv5
// it's not required to fetch tokens from reservoir API, they can be fetched from any other supported marketplace API.
const url = `${deployment.reservoirURL}/tokens/v5?${params}`;
const response = await fetch(url);
if (response.ok) {
const data = await response.json();
// Construct BWLTokens from the fetched tokens
const tokens = (data.tokens as any[])
.map((token) => {
// required fields
const tokenID = token?.token?.tokenId;
const tokenPrice = token?.market?.floorAsk?.price?.amount?.decimal;
const collectionAddress = token?.token?.contract;
// Optional fields
const tokenImage = token?.token?.image ?? "/token-image-placeholder.png";
const collectionName = token?.token?.collection?.name ?? "Unnamed";
// add the token to the array if all required fields are present
if (tokenID != undefined && tokenPrice && collectionAddress) {
return {
tokenID,
tokenPrice,
collectionAddress,
tokenImage,
collectionName,
};
}
// otherwise undefined will be added to the array
})
// remove all undefined values from the array
.filter((token) => token != undefined) as BWLToken[];
// save the fetched tokens in state
setTokens(tokens);
}
};
return (
<section className="flex flex-col space-y-1">
<h2 className="text-2xl font-bold">Buy With Leverage</h2>
<div className="flex space-x-2 items-center">
{/* The collection address input */}
<span>Collection address:</span>
<Input value={collectionAddress} onChange={(e) => setCollectionAddress(e.target.value)} />
{/* The tokenIDs input */}
<span>tokenIDs (comma separated): </span>
<Input value={tokenIDs} onChange={(e) => setTokenIDs(e.target.value)} />
{/* the fetch button */}
<Button type="button" onClick={fetchToken}>
Fetch tokens
</Button>
</div>
<div className="flex items-start">
Fetched tokens:
{/* if there are fetched tokens, display them in a list. If not, display "none" */}
{tokens.length ? (
<div className="flex flex-col ml-4 space-y-1">
{tokens.map((token) => (
<TokenRow token={token} key={token.tokenID} />
))}
</div>
) : (
"none"
)}
{/* this wraps a BuyWithLeverageButton and BuyWithLeverageModal components */}
<BuyWithLeverage tokens={tokens} className="w-56 ml-4" callForActionLink={callForActionLink} />
</div>
</section>
);
};
interface TokenRowProps {
token: BWLToken;
}
// TokenRow is just a component representing a single fetched NFT
const TokenRow = (props: TokenRowProps) => {
const { token } = props;
return (
<div className="flex items-center space-x-3">
<img alt="" className="h-12 w-12 object-cover" src={token.tokenImage} />
<div className="flex flex-col text-sm">
<span className="font-semibold text-msPrimaryLight">
{token.collectionName}
<span className="text-xs font-normal text-gray-500"> #{token.tokenID}</span>
</span>
<span>{token.tokenPrice} ETH</span>
</div>
</div>
);
};
export default BuyWithLeverageSection;