Skip to content

Commit

Permalink
Add revoke approval tool for ERC20 plugin (#157)
Browse files Browse the repository at this point in the history
* Add revoke approval tool

* Fix lint

---------

Co-authored-by: Agustin Armellini Fischer <[email protected]>
  • Loading branch information
toozol and 0xaguspunk authored Dec 31, 2024
1 parent ba3b09a commit 578b310
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 30 deletions.
20 changes: 20 additions & 0 deletions typescript/packages/plugins/erc20/src/erc20.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
GetTokenBalanceParameters,
GetTokenInfoBySymbolParameters,
GetTokenTotalSupplyParameters,
RevokeApprovalParameters,
TransferFromParameters,
TransferParameters,
} from "./parameters";
Expand Down Expand Up @@ -144,6 +145,25 @@ export class Erc20Service {
}
}

@Tool({
description: "Revoke approval for an ERC20 token to an address",
})
async revokeApproval(walletClient: EVMWalletClient, parameters: RevokeApprovalParameters) {
try {
const spender = await walletClient.resolveAddress(parameters.spender);

const hash = await walletClient.sendTransaction({
to: parameters.tokenAddress,
abi: ERC20_ABI,
functionName: "approve",
args: [spender, 0],
});
return hash.hash;
} catch (error) {
throw Error(`Failed to revoke approval: ${error}`);
}
}

@Tool({
description: "Transfer an amount of an ERC20 token from an address to another address",
})
Expand Down
7 changes: 7 additions & 0 deletions typescript/packages/plugins/erc20/src/parameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ export class ApproveParameters extends createToolParameters(
}),
) {}

export class RevokeApprovalParameters extends createToolParameters(
z.object({
tokenAddress: z.string().describe("The address of the token to revoke"),
spender: z.string().describe("The address to revoke the allowance to"),
}),
) {}

export class TransferFromParameters extends createToolParameters(
z.object({
tokenAddress: z.string().describe("The address of the token to transfer"),
Expand Down
40 changes: 10 additions & 30 deletions typescript/packages/wallets/solana/src/SolanaKeypairWalletClient.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
import {
type Keypair,
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import { type Keypair, TransactionMessage, VersionedTransaction } from "@solana/web3.js";
import nacl from "tweetnacl";
import {
type SolanWalletClientCtorParams,
SolanaWalletClient,
} from "./SolanaWalletClient";
import { type SolanWalletClientCtorParams, SolanaWalletClient } from "./SolanaWalletClient";
import type { SolanaTransaction } from "./types";

export type SolanaKeypairWalletClientCtorParams =
SolanWalletClientCtorParams & {
keypair: Keypair;
};
export type SolanaKeypairWalletClientCtorParams = SolanWalletClientCtorParams & {
keypair: Keypair;
};

export class SolanaKeypairWalletClient extends SolanaWalletClient {
#keypair: Keypair;
Expand All @@ -30,31 +22,20 @@ export class SolanaKeypairWalletClient extends SolanaWalletClient {

async signMessage(message: string) {
const messageBytes = Buffer.from(message);
const signature = nacl.sign.detached(
messageBytes,
this.#keypair.secretKey
);
const signature = nacl.sign.detached(messageBytes, this.#keypair.secretKey);
return {
signature: Buffer.from(signature).toString("hex"),
};
}

async sendTransaction({
instructions,
addressLookupTableAddresses = [],
accountsToSign = [],
}: SolanaTransaction) {
async sendTransaction({ instructions, addressLookupTableAddresses = [], accountsToSign = [] }: SolanaTransaction) {
const latestBlockhash = await this.connection.getLatestBlockhash();

const message = new TransactionMessage({
payerKey: this.#keypair.publicKey,
recentBlockhash: latestBlockhash.blockhash,
instructions,
}).compileToV0Message(
await this.getAddressLookupTableAccounts(
addressLookupTableAddresses
)
);
}).compileToV0Message(await this.getAddressLookupTableAccounts(addressLookupTableAddresses));
const transaction = new VersionedTransaction(message);

transaction.sign([this.#keypair, ...accountsToSign]);
Expand All @@ -70,7 +51,7 @@ export class SolanaKeypairWalletClient extends SolanaWalletClient {
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
signature: hash,
},
"confirmed"
"confirmed",
);

return {
Expand All @@ -79,5 +60,4 @@ export class SolanaKeypairWalletClient extends SolanaWalletClient {
}
}

export const solana = (params: SolanaKeypairWalletClientCtorParams) =>
new SolanaKeypairWalletClient(params);
export const solana = (params: SolanaKeypairWalletClientCtorParams) => new SolanaKeypairWalletClient(params);

0 comments on commit 578b310

Please sign in to comment.