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.