2021-05-15 14:19:29 -07:00
|
|
|
import { useState, useEffect, useMemo } from "react";
|
2021-05-15 00:39:56 -07:00
|
|
|
import { SnackbarProvider, useSnackbar } from "notistack";
|
2021-05-15 14:19:29 -07:00
|
|
|
import { Button } from "@material-ui/core";
|
2021-05-12 13:10:52 -07:00
|
|
|
import { Provider } from "@project-serum/anchor";
|
2021-05-12 10:57:22 -07:00
|
|
|
// @ts-ignore
|
2021-05-12 13:10:52 -07:00
|
|
|
import Wallet from "@project-serum/sol-wallet-adapter";
|
2021-05-15 00:39:56 -07:00
|
|
|
import {
|
2021-05-20 02:37:34 -07:00
|
|
|
Signer,
|
2021-05-15 00:39:56 -07:00
|
|
|
ConfirmOptions,
|
|
|
|
Connection,
|
|
|
|
Transaction,
|
|
|
|
TransactionSignature,
|
|
|
|
} from "@solana/web3.js";
|
2021-05-15 14:19:29 -07:00
|
|
|
import {
|
|
|
|
TokenListContainer,
|
|
|
|
TokenListProvider,
|
|
|
|
} from "@solana/spl-token-registry";
|
2021-05-21 14:58:01 -07:00
|
|
|
import Swap from "@project-serum/swap-ui";
|
2021-05-12 13:10:52 -07:00
|
|
|
import "./App.css";
|
2021-05-12 10:57:22 -07:00
|
|
|
|
2021-05-15 00:39:56 -07:00
|
|
|
// App illustrating the use of the Swap component.
|
|
|
|
//
|
|
|
|
// One needs to just provide an Anchor `Provider` and a `TokenListContainer`
|
|
|
|
// to the `Swap` component, and then everything else is taken care of.
|
2021-05-12 10:57:22 -07:00
|
|
|
function App() {
|
2021-05-15 00:39:56 -07:00
|
|
|
return (
|
2021-05-15 16:16:28 -07:00
|
|
|
<SnackbarProvider maxSnack={5} autoHideDuration={8000}>
|
|
|
|
<AppInner />
|
|
|
|
</SnackbarProvider>
|
2021-05-15 00:39:56 -07:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function AppInner() {
|
|
|
|
const { enqueueSnackbar } = useSnackbar();
|
2021-05-12 13:10:52 -07:00
|
|
|
const [isConnected, setIsConnected] = useState(false);
|
2021-05-15 14:19:29 -07:00
|
|
|
const [tokenList, setTokenList] = useState<TokenListContainer | null>(null);
|
2021-05-12 10:57:22 -07:00
|
|
|
|
2021-05-15 14:19:29 -07:00
|
|
|
const [provider, wallet] = useMemo(() => {
|
2021-05-12 13:10:52 -07:00
|
|
|
const opts: ConfirmOptions = {
|
|
|
|
preflightCommitment: "recent",
|
|
|
|
commitment: "recent",
|
|
|
|
};
|
2021-05-13 01:11:13 -07:00
|
|
|
const network = "https://solana-api.projectserum.com";
|
2021-05-12 13:10:52 -07:00
|
|
|
const wallet = new Wallet("https://www.sollet.io", network);
|
|
|
|
const connection = new Connection(network, opts.preflightCommitment);
|
2021-05-15 14:19:29 -07:00
|
|
|
const provider = new NotifyingProvider(
|
|
|
|
connection,
|
|
|
|
wallet,
|
|
|
|
opts,
|
|
|
|
(tx, err) => {
|
|
|
|
if (err) {
|
|
|
|
enqueueSnackbar(`Error: ${err.toString()}`, {
|
|
|
|
variant: "error",
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
enqueueSnackbar("Transaction sent", {
|
|
|
|
variant: "success",
|
|
|
|
action: (
|
|
|
|
<Button
|
|
|
|
color="inherit"
|
|
|
|
component="a"
|
|
|
|
target="_blank"
|
|
|
|
rel="noopener"
|
|
|
|
href={`https://explorer.solana.com/tx/${tx}`}
|
|
|
|
>
|
|
|
|
View on Solana Explorer
|
|
|
|
</Button>
|
|
|
|
),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return [provider, wallet];
|
|
|
|
}, [enqueueSnackbar]);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
new TokenListProvider().resolve().then(setTokenList);
|
|
|
|
}, [setTokenList]);
|
2021-05-12 10:57:22 -07:00
|
|
|
|
2021-05-12 13:10:52 -07:00
|
|
|
// Connect to the wallet.
|
|
|
|
useEffect(() => {
|
2021-05-15 14:19:29 -07:00
|
|
|
wallet.on("connect", () => {
|
|
|
|
enqueueSnackbar("Wallet connected", { variant: "success" });
|
|
|
|
setIsConnected(true);
|
|
|
|
});
|
|
|
|
wallet.on("disconnect", () => {
|
|
|
|
enqueueSnackbar("Wallet disconnected", { variant: "info" });
|
|
|
|
setIsConnected(false);
|
|
|
|
});
|
|
|
|
}, [wallet, enqueueSnackbar]);
|
2021-05-12 10:57:22 -07:00
|
|
|
|
2021-05-15 14:19:29 -07:00
|
|
|
return (
|
2021-05-15 16:16:28 -07:00
|
|
|
<div
|
|
|
|
style={{
|
|
|
|
width: "450px",
|
|
|
|
marginLeft: "auto",
|
|
|
|
marginRight: "auto",
|
|
|
|
position: "absolute",
|
|
|
|
left: 0,
|
|
|
|
right: 0,
|
|
|
|
top: 0,
|
|
|
|
bottom: 0,
|
|
|
|
display: "flex",
|
|
|
|
justifyContent: "center",
|
|
|
|
flexDirection: "column",
|
|
|
|
}}
|
|
|
|
>
|
2021-05-15 14:19:29 -07:00
|
|
|
<Button
|
|
|
|
variant="outlined"
|
|
|
|
onClick={() => (!isConnected ? wallet.connect() : wallet.disconnect())}
|
|
|
|
style={{ position: "fixed", right: 24, top: 24 }}
|
|
|
|
>
|
|
|
|
{!isConnected ? "Connect" : "Disconnect"}
|
|
|
|
</Button>
|
|
|
|
{tokenList && <Swap provider={provider} tokenList={tokenList} />}
|
|
|
|
</div>
|
2021-05-12 10:57:22 -07:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-05-15 00:39:56 -07:00
|
|
|
// Custom provider to display notifications whenever a transaction is sent.
|
|
|
|
//
|
|
|
|
// Note that this is an Anchor wallet/network provider--not a React provider,
|
|
|
|
// so all transactions will be flowing through here, which allows us to
|
|
|
|
// hook in to display all transactions sent from the `Swap` component
|
|
|
|
// as notifications in the parent app.
|
|
|
|
class NotifyingProvider extends Provider {
|
|
|
|
// Function to call whenever the provider sends a transaction;
|
2021-05-15 14:19:29 -07:00
|
|
|
private onTransaction: (
|
|
|
|
tx: TransactionSignature | undefined,
|
|
|
|
err?: Error
|
|
|
|
) => void;
|
2021-05-15 00:39:56 -07:00
|
|
|
|
|
|
|
constructor(
|
|
|
|
connection: Connection,
|
|
|
|
wallet: Wallet,
|
|
|
|
opts: ConfirmOptions,
|
2021-05-15 14:19:29 -07:00
|
|
|
onTransaction: (tx: TransactionSignature | undefined, err?: Error) => void
|
2021-05-15 00:39:56 -07:00
|
|
|
) {
|
|
|
|
super(connection, wallet, opts);
|
|
|
|
this.onTransaction = onTransaction;
|
|
|
|
}
|
|
|
|
|
|
|
|
async send(
|
|
|
|
tx: Transaction,
|
2021-05-20 02:37:34 -07:00
|
|
|
signers?: Array<Signer | undefined>,
|
2021-05-15 00:39:56 -07:00
|
|
|
opts?: ConfirmOptions
|
|
|
|
): Promise<TransactionSignature> {
|
2021-05-15 14:19:29 -07:00
|
|
|
try {
|
|
|
|
const txSig = await super.send(tx, signers, opts);
|
|
|
|
this.onTransaction(txSig);
|
|
|
|
return txSig;
|
|
|
|
} catch (err) {
|
|
|
|
this.onTransaction(undefined, err);
|
2021-05-16 01:02:33 -07:00
|
|
|
return "";
|
2021-05-15 14:19:29 -07:00
|
|
|
}
|
2021-05-15 00:39:56 -07:00
|
|
|
}
|
2021-05-20 00:17:46 -07:00
|
|
|
|
|
|
|
async sendAll(
|
2021-05-20 02:37:34 -07:00
|
|
|
txs: Array<{ tx: Transaction; signers: Array<Signer | undefined> }>,
|
2021-05-20 00:17:46 -07:00
|
|
|
opts?: ConfirmOptions
|
|
|
|
): Promise<Array<TransactionSignature>> {
|
|
|
|
try {
|
|
|
|
const txSigs = await super.sendAll(txs, opts);
|
|
|
|
txSigs.forEach((sig) => {
|
|
|
|
this.onTransaction(sig);
|
|
|
|
});
|
|
|
|
return txSigs;
|
|
|
|
} catch (err) {
|
|
|
|
this.onTransaction(undefined, err);
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
}
|
2021-05-15 00:39:56 -07:00
|
|
|
}
|
|
|
|
|
2021-05-12 10:57:22 -07:00
|
|
|
export default App;
|