Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updated contract to use forge #4

Merged
merged 1 commit into from
Mar 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
"editor.defaultFormatter": "biomejs.biome"
},
"biome.rename": true,
// Disable prettier to avoid conflicts
"prettier.enable": false,
"eslint.enable": false

"[solidity]": {
"editor.defaultFormatter": "JuanBlanco.solidity"
},
"solidity.formatter": "forge",
"prettier.configPath": "./contracts/prettier.config.js"
}
15 changes: 0 additions & 15 deletions backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,3 @@ package-lock.json

node_modules
.env

# Hardhat files
/cache
/artifacts

# TypeChain files
/typechain
/typechain-types

# solidity-coverage files
/coverage
/coverage.json

# Hardhat Ignition default folder for deployments against a local node
ignition/deployments/chain-31337
2 changes: 0 additions & 2 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@
"zod": "^3.24.2"
},
"devDependencies": {
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
"@types/yargs": "^17.0.33",
"bun-types": "latest",
"dotenv": "^16.4.7",
"hardhat": "^2.22.19"
},
"engines": {
"node": ">=22"
Expand Down
58 changes: 0 additions & 58 deletions backend/scripts/deploy-vault-factory.ts

This file was deleted.

119 changes: 60 additions & 59 deletions backend/src/plugins/plugin-sonic/actions/create-vault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,26 @@ import {
elizaLogger,
} from '@elizaos/core';
import { v4 as uuidv4 } from 'uuid';
import { http, createPublicClient, createWalletClient } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { sonic } from 'viem/chains';
import type { Address, PublicClient, WalletClient } from 'viem';
import { z } from 'zod';
import VaultFactoryArtifact from '../../../../../contracts/artifacts/src/contracts/create-vault/VaultFactory.sol/VaultFactory.json';
import { env } from '../../../config/env';
import { ethereumAddressSchema } from '../../../validators/ethereum';
import { VAULT_FACTORY_ABI } from '../constants/vault-factory-abi';
import { initSonicProvider } from '../providers/sonic';

// TODO Move this to a type
interface MessageMetadata {
walletAddress?: string;
walletAddress?: Address;
[key: string]: unknown;
}

const createVaultContentSchema = z.object({
userId: z.string(),
walletAddress: z.string(),
tokenAddress: z.string(),
vaultName: z.string().optional(),
vaultDescription: z.string().optional(),
userId: z.string().uuid(),
walletAddress: ethereumAddressSchema,
agentAddress: ethereumAddressSchema,
vaultFactoryAddress: ethereumAddressSchema,
// FIXME Should be typed
publicClient: z.unknown(),
walletClient: z.unknown(),
});

type CreateVaultContent = z.infer<typeof createVaultContentSchema>;
Expand All @@ -40,52 +42,39 @@ interface CreateVaultResponse {
async function createVault(
params: CreateVaultContent & { runtime: IAgentRuntime },
): Promise<CreateVaultResponse> {
const {
userId,
walletAddress,
tokenAddress,
vaultName,
vaultDescription,
runtime,
} = params;

try {
// Initialize Viem clients
const publicClient = createPublicClient({
chain: sonic,
transport: http('https://rpc.soniclabs.com'),
});

// Create wallet client with private key
const account = privateKeyToAccount(env.EVM_PRIVATE_KEY);
const walletClient = createWalletClient({
account,
chain: sonic,
transport: http('https://rpc.soniclabs.com'),
});
const parsedParams = createVaultContentSchema.parse(params);
const {
userId,
walletAddress,
vaultFactoryAddress,
agentAddress,
publicClient,
walletClient,
} = parsedParams;
const typedPublicClient = publicClient as PublicClient;
const typedWalletClient = walletClient as WalletClient;
const { runtime } = params;

// Create vault through factory
const hash = await walletClient.writeContract({
address: env.VAULT_FACTORY_ADDRESS,
abi: VaultFactoryArtifact.abi,
// Approve from the vault address
const { request } = await typedPublicClient.simulateContract({
account: agentAddress,
address: vaultFactoryAddress,
abi: VAULT_FACTORY_ABI,
functionName: 'createVault',
args: [
tokenAddress as `0x${string}`,
vaultName || 'My Sonic Vault',
vaultDescription || 'AI-managed vault for Sonic users',
'SONIC_VAULT',
],
args: [agentAddress],
});

const receipt = await publicClient.waitForTransactionReceipt({ hash });
const hash = await typedWalletClient.writeContract(request);
const receipt = await typedPublicClient.waitForTransactionReceipt({ hash });

// Log the transaction receipt for debugging
elizaLogger.info('Transaction receipt:', {
logs: receipt.logs,
status: receipt.status,
elizaLogger.info('Successfully created vault', {
contractAddress: receipt.contractAddress,
});

// TODO Add viem parsing here
// Look for the VaultCreated event in the transaction receipt
const vaultCreatedEvent = receipt.logs.find(
(log) =>
Expand Down Expand Up @@ -114,9 +103,6 @@ async function createVault(
vaultAddress,
userId,
walletAddress,
tokenAddress,
vaultName,
vaultDescription,
createdAt: new Date().toISOString(),
transactionHash: hash,
},
Expand All @@ -133,9 +119,6 @@ async function createVault(
userId,
walletAddress,
vaultAddress,
tokenAddress,
vaultName,
vaultDescription,
agentId: runtime.agentId,
transactionHash: hash,
});
Expand Down Expand Up @@ -180,7 +163,24 @@ export const createVaultAction: Action = {
},
],
],
validate: async (_runtime: IAgentRuntime) => {
validate: async (runtime: IAgentRuntime, message: Memory) => {
const vaultFactoryAddress = runtime.getSetting('VAULT_FACTORY_ADDRESS');
if (!vaultFactoryAddress) {
return false;
}
const rpcUrl = runtime.getSetting('SONIC_RPC_URL');
if (!rpcUrl) {
return false;
}
const privateKey = runtime.getSetting('SONIC_PRIVATE_KEY') as `0x${string}`;
if (!privateKey) {
return false;
}
const metadata = message.content.metadata as MessageMetadata;
const walletAddress = metadata?.walletAddress;
if (!walletAddress) {
return false;
}
return true;
},
handler: async (
Expand All @@ -193,10 +193,12 @@ export const createVaultAction: Action = {
callback?: HandlerCallback,
) => {
elizaLogger.log('Create Vault handler called');
const sonicProvider = await initSonicProvider(runtime);

// Extract wallet address from message metadata
const metadata = message.content.metadata as MessageMetadata;
const walletAddress = metadata?.walletAddress;
// Should not happen, it is validated
if (!walletAddress) {
elizaLogger.error('No wallet address provided in message metadata');
if (callback) {
Expand All @@ -208,14 +210,13 @@ export const createVaultAction: Action = {
}

// Use the userId from the message
const createVaultContent = {
const createVaultContent: CreateVaultContent = {
userId: message.userId,
walletAddress,
tokenAddress:
process.env.DEFAULT_TOKEN_ADDRESS ||
'0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38', // Sonic (S) token address
vaultName: 'My Sonic Vault',
vaultDescription: 'AI-managed vault for Sonic users',
agentAddress: sonicProvider.account.address,
vaultFactoryAddress: sonicProvider.vaultFactoryAddress,
publicClient: sonicProvider.getPublicClient(),
walletClient: sonicProvider.getWalletClient(),
};

try {
Expand Down
Loading