AI agent swaps on CoW Swap
CoW swap ensures best prices and fastest execution and minimizes MEV.
You can find a working code example to run locally in our AI agent with Safe Smart Account CoW Swap example repository (opens in a new tab).
Here is a quick guide to get you up and running:
Requirements
- A deployed Safe Smart Account
- The AI agent is a signer on the Safe
- This example assumes, that the threshold of the Safe Smart Account is one, so the AI agent can sign autonomously. If you require more signatures, you have to collect those signatures programmatically of with the Safe Wallet (opens in a new tab).
Let your AI agent send an intent
Setup the Safe Smart Account
Your Safe Smart Account should be deployed. Now, initialize an instance with the Protocol Kit:
_10import Safe from "@safe-global/protocol-kit";_10_10const preExistingSafe = await Safe.init({_10 provider: RPC_URL,_10 signer: AGENT_PRIVATE_KEY,_10 safeAddress: SAFE_ADDRESS,_10});
Send swap intent
Now, you can use the CoW Swap SDK to assemble a transaction that you can sign and execute with your Safe Smart Account. The swap will then be executed.
Please be aware that the CoW Swap's SDK uses Ethers, while Safe's SDK use viem. You will see some warnings in the logs, but the code works nonetheless.
In this example, we buy COW and pay with WETH.
_78import {_78 SwapAdvancedSettings,_78 TradeParameters,_78 TradingSdk,_78 SupportedChainId,_78 OrderKind,_78 SigningScheme,_78} from "@cowprotocol/cow-sdk";_78import { VoidSigner } from "@ethersproject/abstract-signer";_78import { JsonRpcProvider } from "@ethersproject/providers";_78_78const traderParams = {_78 chainId: SupportedChainId.SEPOLIA,_78 signer: new VoidSigner(_78 smartContractWalletAddress: SAFE_ADDRESS,_78 new JsonRpcProvider("https://sepolia.gateway.tenderly.co")_78 ),_78 appCode: "awesome-app",_78};_78_78const cowSdk = new TradingSdk(traderParams, { logs: false });_78_78const parameters: TradeParameters = {_78 kind: OrderKind.SELL,_78 sellToken: WETH_ADDRESS,_78 sellTokenDecimals: 18,_78 buyToken: COW_ADDRESS,_78 buyTokenDecimals: 18,_78 amount: INPUT_AMOUNT,_78};_78_78const advancedParameters: SwapAdvancedSettings = {_78 quoteRequest: {_78 // Specify the signing scheme_78 signingScheme: SigningScheme.PRESIGN,_78 },_78};_78_78const orderId = await cowSdk.postSwapOrder(parameters, advancedParameters);_78_78console.log(`Order ID: [${orderId}]`);_78_78const preSignTransaction = await cowSdk.getPreSignTransaction({_78 orderId,_78 account: smartContractWalletAddress,_78});_78_78const customChain = defineChain({_78 ...sepolia,_78 name: "custom chain",_78 transport: http(RPC_URL),_78});_78_78const publicClient = createPublicClient({_78 chain: customChain,_78 transport: http(RPC_URL),_78});_78_78const safePreSignTx: MetaTransactionData = {_78 to: preSignTransaction.to,_78 value: preSignTransaction.value,_78 data: preSignTransaction.data,_78 operation: OperationType.Call,_78};_78_78const safeTx = await preExistingSafe.createTransaction({_78 transactions: [safePreSignTx],_78 onlyCalls: true,_78});_78_78// You might need to collect more signatures here_78_78const txResponse = await preExistingSafe.executeTransaction(safeTx);_78console.log(`Sent tx hash: [${txResponse.hash}]`);_78console.log("Waiting for the tx to be mined");_78await publicClient.waitForTransactionReceipt({_78 hash: txResponse.hash as `0x${string}`,_78});
Next steps
Now, where your AI agent can execute trades autonomously, you are free to use this power as you like. You can find more specific information in the CoW Swap Trading SDK docs (opens in a new tab).
If you have a technical question about Safe Smart Accounts, feel free to reach out on Stack Exchange (opens in a new tab) with the safe-core tag.