콘텐츠로 건너뛰기

ElizaOS를 사용하여 토큰을 전송하고 스왑할 수 있는 AI 에이전트 만들기

토큰을 전송하고 스왑할 수 있는 AI 에이전트를 만드는 방법을 알아보세요.

5분
ElizaOS를 사용하여 토큰을 전송하고 스왑할 수 있는 AI 에이전트 만들기

AI 에이전트는 환경을 인식하고, 정보를 처리하며, 특정 목표를 달성하기 위해 행동을 취하도록 설계된 자율 프로그램입니다. 이러한 에이전트는 단순한 규칙 기반 봇부터 시간이 지남에 따라 결정을 적응하고 최적화할 수 있는 고급 머신러닝 시스템까지 다양합니다.

블록체인과 DeFi에서 AI 기반 자동화의 부상은 원활하고 지능적인 온체인 상호작용을 위한 새로운 가능성을 열었습니다. 트레이딩, 리스크 평가, 유동성 관리와 같은 작업 자동화부터 복잡한 스마트 컨트랙트 상호작용 실행까지, AI 에이전트는 효율성을 높이고 인간의 개입 필요성을 줄임으로써 dapp을 구축하는 방식을 변화시키고 있습니다.

ElizaOS와 같은 프레임워크를 통해 개발자는 블록체인 프로토콜과 상호작용하고 토큰 스왑, 차익거래, 포트폴리오 관리에 대한 실시간 결정을 내리는 AI 에이전트를 구축할 수 있습니다. 이 가이드에서는 ElizaOS의 내장 기능을 사용하여 자율적으로 트랜잭션을 실행하는 AI 에이전트의 설계, 설정 및 구현 과정을 안내합니다.

사전 요구사항

구축을 시작하기 전에 다음 설정이 완료되어 있는지 확인하세요:

  • Node.js (v23.3.0 이상)

  • PNPM 패키지 매니저

  • 테스트넷 토큰이 있는 EVM 호환 지갑 – 트랜잭션 실행에 필요 (예: Sepolia ETH)

  • RPC 공급자 URL – 애플리케이션을 블록체인에 연결, 예: Infura

  • 모델 공급자용 API 키 – AI 상호작용에 필요 (예: OpenAI)

이 모든 준비가 완료되면 AI 기반 블록체인 에이전트 구축을 시작할 준비가 된 것입니다.

ElizaOS 환경 설정

ElizaOS 저장소를 클론하고 최신 릴리스를 체크아웃합니다.

git clone https://github.com/elizaOS/eliza.git
cd eliza
git checkout $(git describe --tags --abbrev=0)
복사

메인 버전이 작동하지 않는 경우 안정적인 릴리스로 전환할 수 있습니다. 작성 시점 기준으로 stable-11-30 버전이 권장되었습니다. 사용하려면 다음을 실행하세요:

git fetch --all 
git checkout stable-11-30
복사

의존성 설치

pnpm install

환경 변수 설정

cp .env.example .env

`# EVM EVM_PRIVATE_KEY= EVM_PROVIDER_URL=

OPEN AI

OPENAI_API_KEY=`

위의 세부 정보는 ElizaOS가 올바르게 작동하는 데 필수적입니다:

  • EVM_PRIVATE_KEY**:** 트랜잭션 서명을 위한 지갑 개인 키. Eliza가 토큰 전송 및 스왑을 실행할 지갑이므로, Sepolia 테스트넷 ETH가 미리 충전되어 있는지 확인하세요.

  • EVM_PROVIDER_URL**:** 블록체인 노드에 연결하는 RPC 엔드포인트로, AI 에이전트가 네트워크와 상호작용할 수 있게 합니다.

  • OPENAI_API_KEY**:** OpenAI 모델에 대한 접근 권한을 부여하여 AI 에이전트가 지능적인 결정을 내릴 수 있게 합니다.

참고: 개인 키를 안전하게 보관하고 버전 관리에서 제외되도록 하세요.

Eliza 프레임워크의 핵심 개념

Eliza 프레임워크는 네 가지 핵심 구성 요소로 이루어져 있습니다:

  • Characters: AI의 성격, 행동 방식, 커뮤니케이션 스타일을 정의하는 JSON 설정 파일

  • Agents: 메모리 관리, 입력 처리, 행동 실행을 담당하는 런타임 모듈

  • Providers: 상호작용을 향상시키기 위해 컨텍스트와 실시간 정보를 제공하는 데이터 소스

  • Actions: 에이전트가 작업을 수행하고 외부 시스템과 상호작용할 수 있게 하는 실행 가능한 함수

토큰 스왑 및 전송 캐릭터 정의

캐릭터는 AI 에이전트의 커뮤니케이션 스타일, 톤, 응답 일관성을 정의하여 상호작용을 더 자연스럽고 매력적으로 만듭니다. 잘 설계된 캐릭터는 AI가 의도한 목적에 부합하도록 보장합니다.

이 프로젝트에서 구현하고자 하는 주요 기능은 토큰 전송과 스왑이므로, AI 에이전트가 블록체인 프로토콜과 상호작용하고, 트랜잭션을 실행하며, 사용자에게 피드백을 제공하는 방식을 관장하는 Eliza 캐릭터를 정의할 것입니다. 이 캐릭터는 에이전트가 트랜잭션 세부 정보를 명확하게 전달하고, 사전 정의된 보안 규칙을 따르며, 원활한 사용자 경험을 유지하도록 보장합니다.

새 캐릭터 파일을 생성합니다.

cd characters
touch degen.character.json
복사

새로 생성된 파일에 다음 내용을 복사합니다:

{
    "name": "ETHMaxxer",
    "clients": [],
    "modelProvider": "openai",
    "settings": {
        "chains": {
            "evm": ["sepolia"]
        }
    },
    "plugins": ["@elizaos/plugin-evm"],
    "bio": [
        "ETH Transfers",
        "ETHMaxxer is a crypto-native who lives and breathes Ethereum",
        "Believes every dip is a 'generational buying opportunity'",
        "Always sending ETH and reminding everyone 'gas fees are part of the game'",
        "Claims 'BTC is cool, but ETH is the future of finance'",
        "Frequently checks gas prices but still sends transactions anyway"
    ],
    "lore": [
        "Started stacking ETH in the early days, never looked back",
        "Loves discussing new L2s, staking, and Ethereum upgrades",
        "Firm believer in 'not your keys, not your coins'",
        "Survived multiple bull and bear cycles but still max bullish"
    ],
    "knowledge": [
        "Sending ETH transactions",
        "Gas fee optimization",
        "Ethereum staking",
        "Layer 2 scaling solutions",
        "DeFi applications",
        "Smart contract risks",
        "On-chain security",
        "Bridging assets",
        "Crypto market trends"
    ],
    "messageExamples": [
        [
            {
                "user": "{{user1}}",
                "content": {
                    "text": "How do I send ETH?"
                }
            },
            {
                "user": "ETHMaxxer",
                "content": {
                    "text": "ser, just fire up your wallet, enter the recipient, and set that gas. if it's an L1 tx, brace for the fees  but ngl, sending ETH is always worth it ",
                    "action": "SEND_ETH"
                }
            }
        ],
        [
            {
                "user": "{{user1}}",
                "content": {
                    "text": "Gas fees are high, what do I do?"
                }
            },
            {
                "user": "ETHMaxxer",
                "content": {
                    "text": "fren, welcome to the ETH experience . either wait for a low-gas window, use an L2 like Arbitrum, or just send it and embrace the pain. ngmi if you're scared of gas fees "
                }
            }
        ],
        [
            {
                "user": "{{user1}}",
                "content": {
                    "text": "Is ETH going up?"
                }
            },
            {
                "user": "ETHMaxxer",
                "content": {
                    "text": "anon, ETH is always going up... eventually. if not today, then after the next hard fork or bull cycle. remember, '1 ETH = 1 ETH', just hodl "
                }
            }
        ]
    ],
    "postExamples": [
        "gas is pain, but ETH is life ",
        "sending ETH and feeling rich, until I check my gas fees ",
        "L2s are cool, but real maxxers still send ETH on mainnet "
    ],
    "topics": [
        "eth_transfers",
        "ethereum_news",
        "gas_fees",
        "staking",
        "crypto_markets"
    ],
    "style": {
        "all": [
            "Crypto-maximalist",
            "ETH-focused",
            "Slightly degen",
            "Loves talking about gas fees and upgrades"
        ],
        "chat": [
            "Casual",
            "Crypto-slang heavy",
            "Slightly memetic",
            "Uses emojis frequently"
        ],
        "post": ["Short", "Bullish", "Relatable", "Memetic"]
    },
    "adjectives": [
        "ETH-maxi",
        "Bullish",
        "Crypto-native",
        "Gas-tolerant",
        "Future-focused",
        "Layer 2 curious"
    ]
}
복사

위 파일은 ETHMaxxer라는 AI 에이전트의 설정을 정의하며, "modelProvider": "openai"를 지정하고 Sepolia를 지정된 블록체인 네트워크로 설정합니다.

Agents

Eliza 프레임워크에서 에이전트는 AI 캐릭터에 생명을 불어넣는 핵심 런타임 구성 요소입니다. AgentRuntime 클래스를 통해 행동과 상호작용을 관리합니다. AgentRuntime 클래스가 올바르게 작동하려면 몇 가지 핵심 구성 요소가 필요하며, 그 중 일부는 Eliza 프레임워크에서 기본으로 처리됩니다:

  • Database adapter: 메모리 저장, 관계 추적, 지식 관리를 포함한 AI 에이전트의 정보 저장 및 검색을 처리합니다.

  • Plugins: AI 에이전트의 기능을 확장하여 블록체인 및 소셜 미디어와 같은 외부 서비스와의 통합을 가능하게 합니다. 이 프로젝트에서는 AI 에이전트가 블록체인과 상호작용하기 위해 @elizaos/plugin-evm을 사용하도록 지정합니다.

  • Model provider: 응답 처리 및 생성을 위한 AI 모델 소스를 정의합니다. Anthropic, Grok 등 다양한 옵션이 있지만, 이 프로젝트에서는 캐릭터 파일에 정의된 대로 OpenAI를 선택했습니다.

  • Authentication token: 선택한 모델 공급자에 필요합니다. OPENAI_API_KEY와 같은 환경 변수로 전달해야 합니다.

  • Character configuration file: 앞서 정의한 캐릭터 파일로, AI 에이전트의 특성과 행동을 설명합니다.

이 모든 구성 요소는 /agent/src/index.ts 폴더에 정의되어 있습니다. 에이전트에 관련된 AgentRuntime 코드 스니펫은 다음과 같습니다:

return new AgentRuntime({
        databaseAdapter: db,
        token,
        modelProvider: character.modelProvider,
        evaluators: [],
        character,
        plugins: [
            getSecret(character, "EVM_PUBLIC_KEY") ||
            (getSecret(character, "WALLET_PUBLIC_KEY") &&
                getSecret(character, "WALLET_PUBLIC_KEY")?.startsWith("0x"))
                ? evmPlugin
                : null
        ]
})
복사

Providers

Providers는 지갑 통합, 블록체인 상호작용, 데이터 접근과 같은 특수 기능을 처리하여 AI 에이전트가 외부 시스템과 원활하게 연결될 수 있도록 합니다. 트랜잭션 실행, 실시간 데이터 검색, 다양한 서비스 간 상호작용 관리를 위한 게이트웨이 역할을 합니다.

@elizaos/plugin-evm에서 providers는 AI 에이전트가 EVM 호환 블록체인과 상호작용할 수 있게 하여 트랜잭션 전송, 스마트 컨트랙트 쿼리, 블록체인 활동 모니터링을 가능하게 합니다. Infura와 같은 서비스의 RPC 엔드포인트를 활용함으로써 에이전트는 전용 노드를 운영하지 않고도 온체인 작업을 실행할 수 있습니다.

@elizaos/plugin-evm에서 providers가 구현되는 방식은 다음과 같습니다:

export class WalletProvider {
    private cache: NodeCache;
    private cacheKey: string = "evm/wallet";
    private currentChain: SupportedChain = "mainnet";
    private CACHE_EXPIRY_SEC = 5;
    chains: Record<string, Chain> = { ...viemChains };
    account: PrivateKeyAccount;
    constructor(
        accountOrPrivateKey: PrivateKeyAccount | 
복사
0x${string}
,
        private cacheManager: ICacheManager,
        chains?: Record<string, Chain>
    ) {
        this.setAccount(accountOrPrivateKey);
        this.setChains(chains);
        if (chains && Object.keys(chains).length > 0) {
            this.setCurrentChain(Object.keys(chains)[0] as SupportedChain);
        }
        this.cache = new NodeCache({ stdTTL: this.CACHE_EXPIRY_SEC });
    }
    getAddress(): Address {
        return this.account.address;
    }
    getCurrentChain(): Chain {
        return this.chains[this.currentChain];
    }
    getPublicClient(
        chainName: SupportedChain
    ): PublicClient<HttpTransport, Chain, Account | undefined> {
        const transport = this.createHttpTransport(chainName);
        const publicClient = createPublicClient({
            chain: this.chains[chainName],
            transport,
        });
        return publicClient;
    }
    getWalletClient(chainName: SupportedChain): WalletClient {
        const transport = this.createHttpTransport(chainName);
        const walletClient = createWalletClient({
            chain: this.chains[chainName],
            transport,
            account: this.account,
        });
        return walletClient;
    }
    getChainConfigs(chainName: SupportedChain): Chain {
        const chain = viemChains[chainName];
        if (!chain?.id) {
            throw new Error("Invalid chain name");
        }
        return chain;
    }
    async getWalletBalance(): Promise<string | null> {
        const cacheKey = "walletBalance_" + this.currentChain;
        const cachedData = await this.getCachedData<string>(cacheKey);
        if (cachedData) {
            elizaLogger.log(
                "Returning cached wallet balance for chain: " +
                    this.currentChain
            );
            return cachedData;
        }
        try {
            const client = this.getPublicClient(this.currentChain);
            const balance = await client.getBalance({
                address: this.account.address,
            });
            const balanceFormatted = formatUnits(balance, 18);
            this.setCachedData<string>(cacheKey, balanceFormatted);
            elizaLogger.log(
                "Wallet balance cached for chain: ",
                this.currentChain
            );
            return balanceFormatted;
        } catch (error) {
            console.error("Error getting wallet balance:", error);
            return null;
        }
    }
    async getWalletBalanceForChain(
        chainName: SupportedChain
    ): Promise<string | null> {
        try {
            const client = this.getPublicClient(chainName);
            const balance = await client.getBalance({
                address: this.account.address,
            });
            return formatUnits(balance, 18);
        } catch (error) {
            console.error("Error getting wallet balance:", error);
            return null;
        }
    }
    addChain(chain: Record<string, Chain>) {
        this.setChains(chain);
    }  
}
복사

Actions

Actions는 AI 에이전트가 실행할 수 있는 특정 행동을 정의하여 외부 시스템과 상호작용하고, 요청을 처리하며, 작업을 자동화할 수 있게 합니다. 각 action은 트랜잭션 전송, 데이터 검색, 스마트 컨트랙트 호출 실행과 같은 고유한 기능을 수행하도록 설계되어 에이전트가 환경 내에서 효율적으로 작동하도록 보장합니다.

@elizaos/plugin-evm에서 actions는 토큰 전송, 스왑, 블록체인 상호작용을 촉진하여 AI 에이전트가 EVM 호환 네트워크에서 직접 트랜잭션을 실행할 수 있게 합니다. 이러한 actions는 사용자 입력이나 사전 정의된 로직에 의해 트리거되어 블록체인 관련 작업의 원활한 실행을 보장합니다.

@elizaos/plugin-evm에서 토큰 전송 action이 구현되는 방식은 다음과 같습니다:

async transfer(params: TransferParams): Promise<Transaction> {
        console.log(
           
복사
Transferring: ${params.amount} tokens to (${params.toAddress} on ${params.fromChain})

        );
        if (!params.data) {
            params.data = "0x";
        }
        this.walletProvider.switchChain(params.fromChain);
        const walletClient = this.walletProvider.getWalletClient(
            params.fromChain
        );
        try {
            const hash = await walletClient.sendTransaction({
                account: walletClient.account,
                to: params.toAddress,
                value: parseEther(params.amount),
                data: params.data as Hex,
                kzg: {
                    blobToKzgCommitment: function (_: ByteArray): ByteArray {
                        throw new Error("Function not implemented.");
                    },
                    computeBlobKzgProof: function (
                        _blob: ByteArray,
                        _commitment: ByteArray
                    ): ByteArray {
                        throw new Error("Function not implemented.");
                    },
                },
                chain: undefined,
            });
            return {
                hash,
                from: walletClient.account.address,
                to: params.toAddress,
                value: parseEther(params.amount),
                data: params.data as Hex,
            };
        } catch (error) {
            throw new Error(
복사
Transfer failed: ${error.message}
);
        }
    }
복사

이제 환경 변수, 캐릭터 파일을 제공하고 사용할 Eliza 플러그인을 지정했으니, 모든 것을 연결하여 AI 에이전트를 테스트해 보겠습니다.

프로젝트 빌드

pnpm build

캐릭터 실행

pnpm start --character="characters/degen.character.json"

클라이언트 시작

pnpm start:client

이제 에이전트와 상호작용하며 특정 작업을 수행하도록 요청해 보겠습니다.

결론

Ethereum 및 EVM 호환 블록체인과 상호작용하는 AI 에이전트를 구축하면 자동화되고 지능적인 온체인 상호작용을 위한 새로운 가능성이 열립니다. 이 가이드에서는 Characters, Agents, Providers, Actions를 정의하여 에이전트가 자율적으로 토큰을 전송하고 스왑할 수 있도록 하는 과정을 안내했습니다.

ElizaOS의 모듈식 프레임워크를 활용하면 개발자는 블록체인 네트워크와 원활하게 상호작용하는 AI 기반 DeFi 어시스턴트, 트레이딩 봇, 또는 포트폴리오 매니저를 만들 수 있습니다. 이제 기초를 갖추었으니, 기능을 확장하고, 로직을 개선하며, 새로운 기능을 통합하여 온체인 자동화를 향상시키는 실험을 해보세요.

AI가 번역했습니다. 오류가 있을 수 있습니다. 항상 정보를 확인하시기 바랍니다.

번역 평가하기

이 글의 작성자:

  • Kingsley Okonkwo

    공인 이더리움 블록체인 개발자인 Kingsley는 Consensys에서 테크니컬 라이터로 활동하며, 특히 개발자 도구에 중점을 두고 있습니다. Consensys에 합류하기 전, Kingsley는 Gigster와 Braintrust를 포함한 여러 플랫폼에서 프리랜서 백엔드 개발자로 활동했습니다. 5년간의 소프트웨어 개발 경험을 바탕으로, JavaScript(Node.js 및 React), GoLang, SQL, Docker 등의 도구에 능숙합니다. Kingsley는 최신 web3 기술을 활용해 단계별 튜토리얼과 사용 방법 가이드를 제작하는 데 탁월하며, 동료 개발자들이 더 나은 dapp을 구축할 수 있도록 돕고 있습니다. 현재 두바이에 거주하고 있는 Kingsley는 여가 시간에 농구와 축구를 즐깁니다.

    모든 글 읽기