Skip to content

Commit

Permalink
swapDao
Browse files Browse the repository at this point in the history
Signed-off-by: MarcoMandar <[email protected]>
  • Loading branch information
MarcoMandar committed Nov 4, 2024
1 parent af5508e commit 9b6479a
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 2 deletions.
168 changes: 168 additions & 0 deletions core/src/actions/swapDao.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import { Connection, Keypair, PublicKey, Transaction } from "@solana/web3.js";
import fetch from "cross-fetch";
import {
ActionExample,
IAgentRuntime,
Memory,
type Action,
} from "../core/types.ts";

async function getQuote(
baseToken: string,
outputToken: string,
amount: number
): Promise<any> {
const quoteResponse = await fetch(
`https://quote-api.jup.ag/v6/quote?inputMint=${baseToken}&outputMint=${outputToken}&amount=${amount * 10 ** 6}&slippageBps=50`
);
const swapTransaction = await quoteResponse.json();
const swapTransactionBuf = Buffer.from(swapTransaction, "base64");
return new Uint8Array(swapTransactionBuf);
}

async function invokeSwapDao(
connection: Connection,
authority: Keypair,
statePDA: PublicKey,
walletPDA: PublicKey,
instructionData: Buffer
): Promise<string> {
const discriminator = new Uint8Array([
25, 143, 207, 190, 174, 228, 130, 107,
]);

// Combine discriminator and instructionData into a single Uint8Array
const combinedData = new Uint8Array(
discriminator.length + instructionData.length
);
combinedData.set(discriminator, 0);
combinedData.set(instructionData, discriminator.length);

const transaction = new Transaction().add({
programId: new PublicKey("PROGRAM_ID"),
keys: [
{ pubkey: authority.publicKey, isSigner: true, isWritable: true },
{ pubkey: statePDA, isSigner: false, isWritable: true },
{ pubkey: walletPDA, isSigner: false, isWritable: true },
],
data: Buffer.from(combinedData),
});

const signature = await connection.sendTransaction(transaction, [
authority,
]);
await connection.confirmTransaction(signature);
return signature;
}

async function promptConfirmation(): Promise<boolean> {
// confirmation logic here
const confirmSwap = window.confirm("Confirm the token swap?");
return confirmSwap;
}

export const executeSwap: Action = {
name: "EXECUTE_SWAP_DAO",
similes: ["SWAP_TOKENS_DAO", "TOKEN_SWAP_DAO"],
validate: async (runtime: IAgentRuntime, message: Memory) => {
console.log("Message:", message);
return true;
},
description: "Perform a DAO token swap using execute_invoke.",
handler: async (
runtime: IAgentRuntime,
message: Memory
): Promise<boolean> => {
const { inputToken, outputToken, amount } = message.content;

try {
const connection = new Connection(
"https://api.mainnet-beta.solana.com" // better if we use a better rpc
);
const authority = Keypair.fromSecretKey(
Uint8Array.from(
Buffer.from(
runtime.getSetting("WALLET_PRIVATE_KEY"), // should be the authority private key
"base64"
)
)
);
const daoMint = new PublicKey(runtime.getSetting("DAO_MINT")); // DAO mint address

// Derive PDAs
const [statePDA] = await PublicKey.findProgramAddress(
[Buffer.from("state"), daoMint.toBuffer()],
authority.publicKey
);
const [walletPDA] = await PublicKey.findProgramAddress(
[Buffer.from("wallet"), daoMint.toBuffer()],
authority.publicKey
);

const quoteData = await getQuote(
inputToken as string,
outputToken as string,
amount as number
);
console.log("Swap Quote:", quoteData);

const confirmSwap = await promptConfirmation();
if (!confirmSwap) {
console.log("Swap canceled by user");
return false;
}

// Prepare instruction data for swap
const instructionData = Buffer.from(
JSON.stringify({
quote: quoteData.data,
userPublicKey: authority.publicKey.toString(),
wrapAndUnwrapSol: true,
})
);

const txid = await invokeSwapDao(
connection,
authority,
statePDA,
walletPDA,
instructionData
);

console.log("DAO Swap completed successfully!");
console.log(`Transaction ID: ${txid}`);

return true;
} catch (error) {
console.error("Error during DAO token swap:", error);
return false;
}
},
examples: [
[
{
user: "{{user1}}",
content: {
inputTokenSymbol: "SOL",
outputTokenSymbol: "USDC",
inputToken: "So11111111111111111111111111111111111111112",
outputToken: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
amount: 0.1,
},
},
{
user: "{{user2}}",
content: {
text: "Swapping 0.1 SOL for USDC using DAO...",
action: "TOKEN_SWAP_DAO",
},
},
{
user: "{{user2}}",
content: {
text: "DAO Swap completed successfully! Transaction ID: ...",
},
},
],
] as ActionExample[][],
} as Action;
2 changes: 2 additions & 0 deletions core/src/actions/swapUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ export const fetchBuyTransaction = async (

// deserialize the transaction
const swapTransactionBuf = Buffer.from(swapTransaction, "base64");
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'swapTransactionBuf' implicitly has an 'any' type.
var transaction = VersionedTransaction.deserialize(swapTransactionBuf);

// sign the transaction
Expand Down Expand Up @@ -273,6 +274,7 @@ export const fetchSellTransaction = async (

// deserialize the transaction
const swapTransactionBuf = Buffer.from(swapTransaction, "base64");
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'swapTransactionBuf' implicitly has an 'any' type.
var transaction = VersionedTransaction.deserialize(swapTransactionBuf);

// sign the transaction
Expand Down
6 changes: 4 additions & 2 deletions core/src/providers/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Connection } from "@solana/web3.js";
// import fetch from "cross-fetch";
import { IAgentRuntime, Memory, Provider, State } from "../core/types.ts";
import settings from "../core/settings.ts";
import { toBN, BN } from '../utils/bignumber.js';
import { toBN } from "../utils/bignumber.js";
import {
ProcessedTokenData,
TokenSecurityData,
Expand Down Expand Up @@ -620,7 +620,9 @@ export class TokenProvider {
})
.map((holder) => ({
holderAddress: holder.address,
balanceUsd: toBN(holder.balance).multipliedBy(tokenPriceUsd).toFixed(2),
balanceUsd: toBN(holder.balance)
.multipliedBy(tokenPriceUsd)
.toFixed(2),
}));

return highValueHolders;
Expand Down

0 comments on commit 9b6479a

Please sign in to comment.