|
|
@@ -5,6 +5,7 @@ import {
|
|
|
ConnectionProvider,
|
|
|
WalletProvider,
|
|
|
useAnchorWallet,
|
|
|
+ useConnection,
|
|
|
} from "@solana/wallet-adapter-react";
|
|
|
import {
|
|
|
WalletDisconnectButton,
|
|
|
@@ -20,20 +21,31 @@ import * as buffer from "buffer";
|
|
|
import { AnchorProvider, BN, Program, Wallet } from "@coral-xyz/anchor";
|
|
|
import { SendUSDApp, IDL } from "./idl/send_usd_app";
|
|
|
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
|
|
|
+import { useState } from "react";
|
|
|
window.Buffer = buffer.Buffer;
|
|
|
|
|
|
require("@solana/wallet-adapter-react-ui/styles.css");
|
|
|
|
|
|
const SOL_PRICE_FEED_ID =
|
|
|
"0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d";
|
|
|
-async function postPriceUpdate(connection: Connection, wallet?: AnchorWallet) {
|
|
|
- if (wallet === undefined) {
|
|
|
+const SEND_USD_PROGRAM_ID: PublicKey = new PublicKey(
|
|
|
+ "2e5gZD3suxgJgkCg4pkoogxDKszy1SAwokz8mNeZUj4M"
|
|
|
+);
|
|
|
+const HERMES_URL = "https://hermes.pyth.network/";
|
|
|
+const DEVNET_RPC_URL = "https://api.devnet.solana.com";
|
|
|
+
|
|
|
+async function postPriceUpdate(
|
|
|
+ connection: Connection,
|
|
|
+ wallet: AnchorWallet | undefined,
|
|
|
+ destination: PublicKey | undefined,
|
|
|
+ amount: number | undefined
|
|
|
+) {
|
|
|
+ if (!(wallet && destination && amount)) {
|
|
|
return;
|
|
|
} else {
|
|
|
- const priceServiceConnection = new PriceServiceConnection(
|
|
|
- "https://hermes.pyth.network/",
|
|
|
- { priceFeedRequestConfig: { binary: true } }
|
|
|
- );
|
|
|
+ const priceServiceConnection = new PriceServiceConnection(HERMES_URL, {
|
|
|
+ priceFeedRequestConfig: { binary: true },
|
|
|
+ });
|
|
|
const pythSolanaReceiver = new PythSolanaReceiver({
|
|
|
connection,
|
|
|
wallet: wallet as Wallet,
|
|
|
@@ -45,12 +57,12 @@ async function postPriceUpdate(connection: Connection, wallet?: AnchorWallet) {
|
|
|
|
|
|
const sendUsdApp = new Program<SendUSDApp>(
|
|
|
IDL as SendUSDApp,
|
|
|
- new PublicKey("2e5gZD3suxgJgkCg4pkoogxDKszy1SAwokz8mNeZUj4M"),
|
|
|
- new AnchorProvider(connection, wallet, { commitment: "processed" })
|
|
|
+ SEND_USD_PROGRAM_ID,
|
|
|
+ new AnchorProvider(connection, wallet, AnchorProvider.defaultOptions())
|
|
|
);
|
|
|
|
|
|
const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({
|
|
|
- closeUpdateAccounts: false,
|
|
|
+ closeUpdateAccounts: true,
|
|
|
});
|
|
|
await transactionBuilder.addPostPriceUpdates([priceUpdateData[0]]);
|
|
|
|
|
|
@@ -61,11 +73,9 @@ async function postPriceUpdate(connection: Connection, wallet?: AnchorWallet) {
|
|
|
return [
|
|
|
{
|
|
|
instruction: await sendUsdApp.methods
|
|
|
- .send(new BN(1))
|
|
|
+ .send(new BN(amount))
|
|
|
.accounts({
|
|
|
- destination: new PublicKey(
|
|
|
- "BTwXQZS3EzfxBkv2A54estmn9YbmcpmRWeFP4f3avLi4"
|
|
|
- ),
|
|
|
+ destination,
|
|
|
priceUpdate: getPriceUpdateAccount(SOL_PRICE_FEED_ID),
|
|
|
})
|
|
|
.instruction(),
|
|
|
@@ -84,14 +94,22 @@ async function postPriceUpdate(connection: Connection, wallet?: AnchorWallet) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-function Button() {
|
|
|
- const connection = new Connection("https://api.devnet.solana.com");
|
|
|
+function Button(props: {
|
|
|
+ destination: PublicKey | undefined;
|
|
|
+ amount: number | undefined;
|
|
|
+}) {
|
|
|
+ const connectionContext = useConnection();
|
|
|
const wallet = useAnchorWallet();
|
|
|
|
|
|
return (
|
|
|
<button
|
|
|
onClick={async () => {
|
|
|
- await postPriceUpdate(connection, wallet);
|
|
|
+ await postPriceUpdate(
|
|
|
+ connectionContext.connection,
|
|
|
+ wallet,
|
|
|
+ props.destination,
|
|
|
+ props.amount
|
|
|
+ );
|
|
|
}}
|
|
|
>
|
|
|
Send
|
|
|
@@ -100,8 +118,26 @@ function Button() {
|
|
|
}
|
|
|
|
|
|
function App() {
|
|
|
+ const [destination, setDestination] = useState<PublicKey>();
|
|
|
+ const [amount, setAmount] = useState<number>();
|
|
|
+
|
|
|
+ const handleSetDestination = (event: any) => {
|
|
|
+ try {
|
|
|
+ setDestination(new PublicKey(event.target.value));
|
|
|
+ } catch (e) {
|
|
|
+ setDestination(undefined);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const handleSetAmount = (event: any) => {
|
|
|
+ try {
|
|
|
+ setAmount(parseInt(event.target.value));
|
|
|
+ } catch (e) {
|
|
|
+ setAmount(undefined);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
return (
|
|
|
- <ConnectionProvider endpoint={"https://api.devnet.solana.com"}>
|
|
|
+ <ConnectionProvider endpoint={DEVNET_RPC_URL}>
|
|
|
<WalletProvider wallets={[]} autoConnect>
|
|
|
<WalletModalProvider>
|
|
|
<div className="App">
|
|
|
@@ -109,8 +145,25 @@ function App() {
|
|
|
<img src={logo} className="App-logo" alt="logo" />
|
|
|
<WalletMultiButton />
|
|
|
<WalletDisconnectButton />
|
|
|
- <p>Click to send a 1 usd to the hard-coded account</p>
|
|
|
- <Button />
|
|
|
+ <p>Click to send the amount of USD in SOL</p>
|
|
|
+ <p style={{ fontSize: "16px" }}>
|
|
|
+ Destination (paste a Solana public key)
|
|
|
+ </p>
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ value={destination ? destination.toString() : ""}
|
|
|
+ onChange={handleSetDestination}
|
|
|
+ style={{ width: "100%", height: "40px", fontSize: "16px" }}
|
|
|
+ />
|
|
|
+ <p style={{ fontSize: "16px" }}>Amount (USD)</p>
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ value={amount ? amount.toString() : ""}
|
|
|
+ onChange={handleSetAmount}
|
|
|
+ style={{ width: "100%", height: "40px", fontSize: "16px" }}
|
|
|
+ />
|
|
|
+
|
|
|
+ <Button destination={destination} amount={amount} />
|
|
|
</header>
|
|
|
</div>
|
|
|
</WalletModalProvider>
|