Wallet API supports smart contract writes, reads, smart contract token deployments, and message signing. This allows developers to unlock a wide range of onchain activities while abstracting complexity from end-users.

Example Use Cases

  • Telegram bots for anything: Beyond swapping and sending, developers can create Telegram bots for any smart contract functionality.
  • Multi-step smart contract interactions: Create complex, programmatic DeFi applications that abstract difficult steps from your user. Truly programmatic money legos.

Smart Contract Writes

Smart contracts live on a blockchain and programmatically enforce and execute the terms of an agreement. Integrating smart contracts with API Wallets enables:

  • Complex, multi-step operations triggered by a single user action.
  • Offchain actions with onchain verification and execution.
  • Limitless interactions with any onchain app or protocol.

Examples

Invoking (Calling) a Contract

We natively support the following standard contract interfaces, without you providing an ABI:

However, any other contracts require providing the ABI. If you are interested in cached ABIs for more common smart contracts, reach out to us in the #wallet-api channel of the CDP Discord.

A contract ABI (Application Binary Interface) is the way to interact with a smart contract, both externally and contract-to-contract. It is a file defining the various methods and parameters of the contract.

The SDK also supports payable transactions, which are transactions that send ETH to the contract. See the Basename Registration guide for an example of a payable transaction.

Transfer an ERC-721 NFT

Here’s an example of using invokeContract to transfer an ERC-721 NFT:

    import { Coinbase, Wallet } from "@coinbase/coinbase-sdk";
    import os from "os";

    const coinbase = Coinbase.configureFromJson({ filePath: `${os.homedir()}/Downloads/cdp_api_key.json`, useServerSigner: true });

    const wallet = await Wallet.create({ networkId: Coinbase.networks.EthereumMainnet });

    // Since this is an ERC-721 NFT, there's no need to define the ABI
    const transferFromArgs = {
      from: "0xFrom",
      to: "0xmyEthereumAddress",
      tokenId: "1000",
    };

    const contractInvocation = await wallet.invokeContract({
      contractAddress: "0xYourNFTContractAddress",
      method: "transferFrom",
      args: transferFromArgs,
    });

    // Wait for the contract invocation transaction to land on-chain.
    await contractInvocation.wait();

Invoking an arbitrary smart contract

This is an example of using invokeContract on an arbitrary contract, where the ABI must be explicitly provided.

    // Define the ABI of the contract function you want to interact with
    const abi = [
      {
        name: "transfer",
        type: "function",
        inputs: [
          { name: "to", type: "address" },
          { name: "value", type: "uint256" },
        ],
        outputs: [{ name: "", type: "uint256" }],
        stateMutability: "nonpayable",
      },
    ];

    const transferArgs = {
      to: "0xmyEthereumAddress",
      value: "100",
    };

    const contractInvocation = await wallet.invokeContract({
      contractAddress: "0xYourContractAddress",
      method: "transfer",
      args: transferArgs,
      abi,
    });

    // Wait for the contract invocation transaction to land on-chain.
    await contractInvocation.wait();

Viewing transaction receipts and logs

The CDP SDK supports parsing transaction receipts and logs from contract invocations. Here’s an example.

    const transferArgs = {
      to: "0xmyEthereumAddress",
      value: "1",
    };

    const contractInvocation = await wallet.invokeContract({
      contractAddress: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", // USDC contract on Base Sepolia
      method: "transfer",
      args: transferArgs,
    });
    
    await contractInvocation.wait();

    // Get the transaction content and receipt.
    const transactionContent = contractInvocation.getTransaction().content();
    const receipt = transactionContent.receipt;

    const logs = receipt.logs;

    for (const log of logs) {
        console.log(log.address); // Contract address that emitted the log event
        console.log(log.topics); // Array of decoded topics for the log event
        console.log(log.data); // Data for the log event
    }

Smart Contract Reads

Smart contract support being queried and returning state data without explicitly modifying their state. Readable functions are useful for retrieving current contract state, calculating values, or checking conditions before performing transactions.

Including an ABI is optional, but without it, the CDP SDK will not be able to determine the return type of the function, and the return value will not be parsed. With an ABI, Node.js types are inferred and can be used directly. In Python, the SDK will automatically convert to the expected type at runtime.

Examples

Here’s an example of reading from a smart contract using the CDP SDK:

    import { Coinbase, readContract } from "@coinbase/coinbase-sdk";

// balance is automatically of type bigint
const balance = await readContract({
	networkId: "base-mainnet",
	abi: erc20Abi,
	contractAddress: USDC_BASE_MAINNET_ADDRESS as 0x${string},
	method: "balanceOf",
args: { account: "0xF977814e90dA44bFA03b6295A0616a897441aceC" },
});

console.log(balance);

// balance is of type unknown, so as bigint is needed
const balance = await readContract({
	networkId: "base-mainnet",
	contractAddress: USDC_BASE_MAINNET_ADDRESS as 0x${string},
	method: "balanceOf",
	args: { account: "0xF977814e90dA44bFA03b6295A0616a897441aceC" },
}) as bigint;