Browse Source

feat(xc_admin_frontend): add priority fees to approval/rejection (#1353)

* Make room for compute ixs

* Continue

* Fix syntax

* Checkpoint

* Cleanup

* Cleanup

* Go
guibescos 1 năm trước cách đây
mục cha
commit
7b01f2a1f9

+ 77 - 15
governance/xc_admin/packages/xc_admin_frontend/components/tabs/Proposals.tsx

@@ -1,6 +1,12 @@
 import * as Tooltip from '@radix-ui/react-tooltip'
 import { useWallet } from '@solana/wallet-adapter-react'
-import { AccountMeta, Keypair, PublicKey, SystemProgram } from '@solana/web3.js'
+import {
+  AccountMeta,
+  Keypair,
+  PublicKey,
+  SystemProgram,
+  TransactionInstruction,
+} from '@solana/web3.js'
 import { MultisigAccount, TransactionAccount } from '@sqds/mesh/lib/types'
 import { useRouter } from 'next/router'
 import { Fragment, useCallback, useContext, useEffect, useState } from 'react'
@@ -40,6 +46,12 @@ import {
 
 import { getMappingCluster, isPubkey } from '../InstructionViews/utils'
 import { getPythProgramKeyForCluster, PythCluster } from '@pythnetwork/client'
+import {
+  DEFAULT_PRIORITY_FEE_CONFIG,
+  TransactionBuilder,
+  sendTransactions,
+} from '@pythnetwork/solana-utils'
+import { Wallet } from '@coral-xyz/anchor'
 const ProposalRow = ({
   proposal,
   multisig,
@@ -369,13 +381,35 @@ const Proposal = ({
   }, [cluster, proposal, squads, connection])
 
   const handleClick = async (
-    handler: (squad: SquadsMesh, proposalKey: PublicKey) => any,
+    instructionGenerator: (
+      squad: SquadsMesh,
+      vaultKey: PublicKey,
+      proposalKey: PublicKey
+    ) => Promise<TransactionInstruction>,
     msg: string
   ) => {
     if (proposal && squads) {
       try {
         setIsTransactionLoading(true)
-        await handler(squads, proposal.publicKey)
+        const instruction = await instructionGenerator(
+          squads,
+          proposal.ms,
+          proposal.publicKey
+        )
+        const builder = new TransactionBuilder(
+          squads.wallet.publicKey,
+          squads.connection
+        )
+        builder.addInstruction({ instruction, signers: [] })
+        const versionedTxs = await builder.getVersionedTransactions(
+          DEFAULT_PRIORITY_FEE_CONFIG
+        )
+        await sendTransactions(
+          versionedTxs,
+          squads.connection,
+          squads.wallet as Wallet
+        )
+
         if (refreshData) await refreshData().fetchData()
         toast.success(msg)
       } catch (e: any) {
@@ -387,27 +421,55 @@ const Proposal = ({
   }
 
   const handleClickApprove = async () => {
-    await handleClick(async (squad: SquadsMesh, proposalKey: PublicKey) => {
-      await squad.approveTransaction(proposalKey)
-    }, `Approved proposal ${proposal?.publicKey.toBase58()}`)
+    await handleClick(
+      async (
+        squad: SquadsMesh,
+        vaultKey: PublicKey,
+        proposalKey: PublicKey
+      ): Promise<TransactionInstruction> => {
+        return await squad.buildApproveTransaction(vaultKey, proposalKey)
+      },
+      `Approved proposal ${proposal?.publicKey.toBase58()}`
+    )
   }
 
   const handleClickReject = async () => {
-    await handleClick(async (squad: SquadsMesh, proposalKey: PublicKey) => {
-      await squad.rejectTransaction(proposalKey)
-    }, `Rejected proposal ${proposal?.publicKey.toBase58()}`)
+    await handleClick(
+      async (
+        squad: SquadsMesh,
+        vaultKey: PublicKey,
+        proposalKey: PublicKey
+      ): Promise<TransactionInstruction> => {
+        return await squad.buildRejectTransaction(vaultKey, proposalKey)
+      },
+      `Rejected proposal ${proposal?.publicKey.toBase58()}`
+    )
   }
 
   const handleClickExecute = async () => {
-    await handleClick(async (squad: SquadsMesh, proposalKey: PublicKey) => {
-      await squad.executeTransaction(proposalKey)
-    }, `Executed proposal ${proposal?.publicKey.toBase58()}`)
+    await handleClick(
+      async (
+        squad: SquadsMesh,
+        vaultKey: PublicKey,
+        proposalKey: PublicKey
+      ): Promise<TransactionInstruction> => {
+        return await squad.buildExecuteTransaction(proposalKey)
+      },
+      `Executed proposal ${proposal?.publicKey.toBase58()}`
+    )
   }
 
   const handleClickCancel = async () => {
-    await handleClick(async (squad: SquadsMesh, proposalKey: PublicKey) => {
-      await squad.cancelTransaction(proposalKey)
-    }, `Cancelled proposal ${proposal?.publicKey.toBase58()}`)
+    await handleClick(
+      async (
+        squad: SquadsMesh,
+        vaultKey: PublicKey,
+        proposalKey: PublicKey
+      ): Promise<TransactionInstruction> => {
+        return await squad.buildCancelTransaction(vaultKey, proposalKey)
+      },
+      `Cancelled proposal ${proposal?.publicKey.toBase58()}`
+    )
   }
 
   return proposal !== undefined &&

+ 2 - 0
package-lock.json

@@ -59319,6 +59319,7 @@
       "version": "0.1.0",
       "license": "Apache-2.0",
       "dependencies": {
+        "@coral-xyz/anchor": "^0.29.0",
         "@solana/web3.js": "^1.90.0"
       },
       "devDependencies": {
@@ -71207,6 +71208,7 @@
     "@pythnetwork/solana-utils": {
       "version": "file:target_chains/solana/sdk/js/solana_utils",
       "requires": {
+        "@coral-xyz/anchor": "*",
         "@solana/web3.js": "^1.90.0",
         "@types/jest": "^29.4.0",
         "@typescript-eslint/eslint-plugin": "^5.20.0",

+ 1 - 0
target_chains/solana/sdk/js/solana_utils/package.json

@@ -42,6 +42,7 @@
     "typescript": "^4.6.3"
   },
   "dependencies": {
+    "@coral-xyz/anchor": "^0.29.0",
     "@solana/web3.js": "^1.90.0"
   }
 }

+ 2 - 0
target_chains/solana/sdk/js/solana_utils/src/index.ts

@@ -5,4 +5,6 @@ export {
   InstructionWithEphemeralSigners,
   PACKET_DATA_SIZE_WITH_ROOM_FOR_COMPUTE_BUDGET,
   PriorityFeeConfig,
+  sendTransactions,
+  DEFAULT_PRIORITY_FEE_CONFIG,
 } from "./transaction";

+ 23 - 0
target_chains/solana/sdk/js/solana_utils/src/transaction.ts

@@ -1,5 +1,7 @@
+import { AnchorProvider, Wallet } from "@coral-xyz/anchor";
 import {
   ComputeBudgetProgram,
+  ConfirmOptions,
   Connection,
   PACKET_DATA_SIZE,
   PublicKey,
@@ -24,6 +26,10 @@ export type PriorityFeeConfig = {
   computeUnitPriceMicroLamports?: number;
 };
 
+export const DEFAULT_PRIORITY_FEE_CONFIG: PriorityFeeConfig = {
+  computeUnitPriceMicroLamports: 50000,
+};
+
 /**
  * Get the size of a transaction that would contain the provided array of instructions
  */
@@ -240,3 +246,20 @@ export class TransactionBuilder {
     }
   }
 }
+
+export async function sendTransactions(
+  transactions: {
+    tx: VersionedTransaction | Transaction;
+    signers?: Signer[] | undefined;
+  }[],
+  connection: Connection,
+  wallet: Wallet,
+  opts?: ConfirmOptions
+) {
+  if (opts === undefined) {
+    opts = AnchorProvider.defaultOptions();
+  }
+
+  const provider = new AnchorProvider(connection, wallet, opts);
+  await provider.sendAll(transactions);
+}