Skip to main content
For certain low-risk, high-frequency transactions, bypassing the multi-signature requirement can help streamline operations, especially when tasks are time-sensitive or require frequent interaction. Cobo’s Smart Contract Wallets (Safe{Wallet}) provide an efficient solution by allowing you to authorize a Delegate—either an address from your MPC Wallet or an external EOA wallet—to initiate these actions with a single signature, simplifying execution without compromising control. In this guide, we’ll demonstrate how to configure both an MPC Wallet and an external EOA wallet to claim farming rewards automatically.

Use an MPC Wallet as the Delegate

Assume you have a Safe{Wallet} on the Base chain with ETH deposited in the Stargate protocol for yield farming. You can use an MPC Wallet to perform automated, scheduled reward collection by using the WaaS API.
  1. Before you start, refer to Get started with Smart Contract Wallets to complete the initial setup, including installing the WaaS SDK and importing the Safe{Wallet} to Cobo Portal.
  2. Configure an on-chain risk control policy to approve the claim method initiated via the MPC Wallet address automatically.
    1. Select the MPC Wallet address as the Delegate.
    2. Set Condition as Custom Contract Calls.
    3. Select Method-Level.
    4. Enter the address of the Stargate staking contract as the target contract, and select claim as the method.
    5. Click Submit to initiate a multi-sig transaction. Ask the Safe{Wallet} signers for confirmation.
    set mpc as delegate for stargate rewards collection
  3. Execute the following code to claim rewards daily at 9 a.m. The sample code uses the Call smart contract operation to interact with the Stargate contract.
import schedule
import time
from web3 import Web3
import cobo_waas2

# Specify the Stargate contract address
STG_CLAIM_CONTRACT = "0xdfc47dcef7e8f9ab19a1b8af3eecf000c7ea0b80"
# Get the ABI from Etherscan
STG_CLAIM_ABI = []
# Specify the Stargate pool address
STG_ETH_POOL = "0x98fB8522d891F43B771e2d27367b41Ba138D0B80"
w3 = Web3(Web3.HTTPProvider("<RPC_URL>")) 
contract = w3.eth.contract(address=STG_CLAIM_CONTRACT, abi=STG_CLAIM_ABI)

data = contract.encodeABI("claim", [[STG_ETH_POOL]])

def get_delegate(wallet_id, request: cobo_waas2.SafeWalletDelegates):
# Enter a context with an instance of the API client
    with cobo_waas2.ApiClient(configuration) as api_client:
        # Create an instance of the API class
        wallet_api_instance = cobo_waas2.WalletsSmartContractWalletsApi(api_client)
        try:
            # Call the List Delegates operation to retrieve available Delegates
            api_response = wallet_api_instance.list_safe_wallet_delegates(
                wallet_id=wallet_id,
                safe_wallet_delegates=request
            )
            if not api_response:
                raise Exception("No delegate found")
            print("The response of WalletsApi->list_safe_wallet_delegates:")
            print(json.dumps(api_response[0].to_dict(), indent=2))
            return api_response[0]
        except Exception as e:
            print("Exception when calling WalletsApi: %s\n", e)

def get_wallet(wallet_id) -> cobo_waas2.SafeWallet:
    with cobo_waas2.ApiClient(configuration) as api_client:
        # Create an instance of the API class
        wallet_api_instance = cobo_waas2.WalletsApi(api_client)
        try:
            # Call the Get wallet information operation to retrieve the wallet information, including the wallet address
            api_response = wallet_api_instance.get_wallet_by_id(
                wallet_id=wallet_id
            )
            print("The response of WalletsApi->get_wallet_by_id:")
            print(json.dumps(api_response.to_dict(), indent=2))
            return api_response.actual_instance.actual_instance
        except Exception as e:
            print("Exception when calling WalletsApi: %s\n", e)


def contract_call(wallet_id, contract_address, data, value):
    contract_call_request = cobo_waas2.SafeWalletDelegates(
            actual_instance=cobo_waas2.SafeWalletDelegatesContractCall(
                request_type=cobo_waas2.EstimateFeeRequestType.CONTRACTCALL,
                address=contract_address,
                calldata=data,
                value=value,
            )
        )
    delegate = get_delegate(wallet_id, contract_call_request)
    wallet = get_wallet(wallet_id)

    with cobo_waas2.ApiClient(configuration) as api_client:
        wallet_api_instance = cobo_waas2.TransactionsApi(api_client)
        try:
            # Use the Call smart contract operation to interact with the Stargate contract
            api_response = wallet_api_instance.create_contract_call_transaction(
                cobo_waas2.ContractCallParams(
                    request_id=str(uuid.uuid4()),
                    chain_id=wallet.chain_id,
                    source=cobo_waas2.ContractCallSource(
                        actual_instance=cobo_waas2.SafeContractCallSource(
                            source_type=cobo_waas2.ContractCallSourceType.SAFE_WALLET,
                            wallet_id=wallet_id,
                            address=wallet.safe_address,
                            delegate=delegate,
                        )
                    ),
                    destination=cobo_waas2.ContractCallDestination(
                        actual_instance=cobo_waas2.EvmContractCallDestination(
                            destination_type=cobo_waas2.ContractCallDestinationType.EVM_CONTRACT,
                            address=contract_address,
                            calldata=data,
                            value=value,
                        ),
                    ),
                    category_names=["<CATEGORY_NAME>"],
                    description="<DESCRIPTION>",
                )
            )
            print("The response of TransactionsApi->create_contract_call_transaction:")
            print(json.dumps(api_response.to_dict(), indent=2))
        except Exception as e:
            print("Exception when calling TransactionsApi: %s\n", e)


def daily_contract_call():
    print("claim stargate")
    contract_call(
        wallet_id=wallet_id,
        contract_address=STG_CLAIM_CONTRACT,
        data=data,
        value="0",
    )

# Schedule the contract call to run every day at 9:00 a.m.
schedule.every().day.at("09:00").do(daily_contract_call)

# Keep the script running
while True:
    schedule.run_pending()
    time.sleep(1)

Use an external EOA wallet as the Delegate

You can also use external EOA wallets that are not created through Cobo Portal to claim rewards. The initial steps are similar to those for MPC Wallets, but you will set the EOA wallet address as the Delegate and adjust the on-chain risk control policy accordingly. Instead of using the WaaS API, the EOA wallet interacts with Safe{Wallet} by using functions provided by Cobo Safe. The process can be outlined in the following steps:
  1. Build a claim transaction to collect farming rewards from Stargate.
  2. Wrap the claim transaction within a Cobo Safe transaction.
  3. Initiate the Cobo Safe transaction via the EOA wallet.
  4. Use the EOA wallet to sign the transaction and send it to the network.
import json
from web3 import Web3
import cobo_waas2

import os
from eth_account import Account

# Get the private key from the environment variable
PRIVATE_KEY = os.getenv('ETH_PRIVATE_KEY')
# Create the account object
account = Account.from_key(PRIVATE_KEY)
w3 = Web3(Web3.HTTPProvider("<RPC_URL>")) 

def get_wallet(wallet_id) -> cobo_waas2.SafeWallet:
    with cobo_waas2.ApiClient(configuration) as api_client:
        # Create an instance of the API class
        wallet_api_instance = cobo_waas2.WalletsApi(api_client)
        try:
            # Call the Get wallet information operation to retrieve the wallet information, including the wallet address
            api_response = wallet_api_instance.get_wallet_by_id(
                wallet_id=wallet_id
            )
            print("The response of WalletsApi->get_wallet_by_id:")
            print(json.dumps(api_response.to_dict(), indent=2))
            return api_response.actual_instance.actual_instance
        except Exception as e:
            print("Exception when calling WalletsApi: %s\n", e)


# Enter the wallet ID found in Cobo Portal 
wallet = get_wallet("<YOUR_WALLET_ID>")
# Get the address of Cobo Safe
cobo_safe_address = wallet.cobo_safe_address
# Get the ABI from Etherscan
COBO_SAFE_ABI = [] 

# Specify the Stargate contract address 
STG_CLAIM_CONTRACT = "0xdfc47dcef7e8f9ab19a1b8af3eecf000c7ea0b80"
# Get the ABI from Etherscan
STG_CLAIM_ABI = []
STG_ETH_POOL = "0x98fB8522d891F43B771e2d27367b41Ba138D0B80"
stg_contract = w3.eth.contract(address=STG_CLAIM_CONTRACT, abi=STG_CLAIM_ABI)
# Build Starget claim transaction
data = stg_contract.encodeABI("claim", [[STG_ETH_POOL]])

# Build a Cobo Safe transaction
cobo_safe_contract = w3.eth.contract(address=cobo_safe_address, abi=COBO_SAFE_ABI)
call_datas = [
    [
        0,
        Web3.to_checksum_address(STARGATE_STAKING),
        0,
        Web3.to_bytes(hexstr=data),
        b"",
        b"",
    ]
]

# Build the transaction for the EOA wallet. The transaction initiates a Cobo Safe transaction via the EOA account. 
transaction = cobo_safe_contract.functions.execTransactions(call_datas).build_transaction({
    'from': account.address,
    'nonce': w3.eth.get_transaction_count(account.address),
    # Set a gas fee limit
    'gas': 200000,
    'gasPrice': w3.eth.gas_price,
})

# Sign the transaction
signed_tx = account.sign_transaction(transaction)
# Send the transaction 
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Transaction sent with hash: {tx_hash.hex()}")
Feel free to share your feedback to improve our documentation!