Skip to content

Commit

Permalink
feat: Migrate Superfluid py to 0.1.0 (coinbase#357)
Browse files Browse the repository at this point in the history
  • Loading branch information
John-peterson-coinbase authored and mikeghen committed Feb 13, 2025
1 parent 4557a8a commit ee1153c
Show file tree
Hide file tree
Showing 11 changed files with 640 additions and 10 deletions.
2 changes: 2 additions & 0 deletions python/coinbase-agentkit/coinbase_agentkit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
erc20_action_provider,
morpho_action_provider,
pyth_action_provider,
superfluid_action_provider,
twitter_action_provider,
wallet_action_provider,
weth_action_provider,
Expand Down Expand Up @@ -47,4 +48,5 @@
"twitter_action_provider",
"wallet_action_provider",
"weth_action_provider",
"superfluid_action_provider",
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
from .erc20.erc20_action_provider import ERC20ActionProvider, erc20_action_provider
from .morpho.morpho_action_provider import MorphoActionProvider, morpho_action_provider
from .pyth.pyth_action_provider import PythActionProvider, pyth_action_provider
from .superfluid.superfluid_action_provider import (
SuperfluidActionProvider,
superfluid_action_provider,
)
from .twitter.twitter_action_provider import TwitterActionProvider, twitter_action_provider
from .wallet.wallet_action_provider import WalletActionProvider, wallet_action_provider
from .weth.weth_action_provider import WethActionProvider, weth_action_provider
Expand All @@ -35,4 +39,6 @@
"weth_action_provider",
"BasenameActionProvider",
"basename_action_provider",
"SuperfluidActionProvider",
"superfluid_action_provider",
]
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ def deposit(self, wallet: EvmWalletProvider, args: dict[str, Any]) -> str:
"data": encoded_data,
}

hash = wallet.send_transaction(params)
wallet.wait_for_transaction_receipt(hash)
tx_hash = wallet.send_transaction(params)
wallet.wait_for_transaction_receipt(tx_hash)

return f"Deposited {args['assets']} to Morpho Vault {args['vault_address']} with transaction hash: {hash}"
return f"Deposited {args['assets']} to Morpho Vault {args['vault_address']} with transaction hash: {tx_hash}"

except Exception as e:
return f"Error depositing to Morpho Vault: {e!s}"
Expand Down Expand Up @@ -105,10 +105,10 @@ def withdraw(self, wallet: EvmWalletProvider, args: dict[str, Any]) -> str:
"data": encoded_data,
}

hash = wallet.send_transaction(params)
wallet.wait_for_transaction_receipt(hash)
tx_hash = wallet.send_transaction(params)
wallet.wait_for_transaction_receipt(tx_hash)

return f"Withdrawn {args['assets']} from Morpho Vault {args['vault_address']} with transaction hash: {hash}"
return f"Withdrawn {args['assets']} from Morpho Vault {args['vault_address']} with transaction hash: {tx_hash}"

except Exception as e:
return f"Error withdrawing from Morpho Vault: {e!s}"
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Constants for Superfluid action provider."""

SUPERFLUID_HOST_ADDRESS = "0xcfA132E353cB4E398080B9700609bb008eceB125"

CREATE_ABI = [
{
"inputs": [
{
"internalType": "contract ISuperToken",
"name": "token",
"type": "address",
},
{"internalType": "address", "name": "sender", "type": "address"},
{"internalType": "address", "name": "receiver", "type": "address"},
{"internalType": "int96", "name": "flowrate", "type": "int96"},
{"internalType": "bytes", "name": "userData", "type": "bytes"},
],
"name": "createFlow",
"outputs": [{"internalType": "bool", "name": "", "type": "bool"}],
"stateMutability": "nonpayable",
"type": "function",
}
]

UPDATE_ABI = [
{
"inputs": [
{
"internalType": "contract ISuperToken",
"name": "token",
"type": "address",
},
{"internalType": "address", "name": "sender", "type": "address"},
{"internalType": "address", "name": "receiver", "type": "address"},
{"internalType": "int96", "name": "flowrate", "type": "int96"},
{"internalType": "bytes", "name": "userData", "type": "bytes"},
],
"name": "updateFlow",
"outputs": [{"internalType": "bool", "name": "", "type": "bool"}],
"stateMutability": "nonpayable",
"type": "function",
}
]

DELETE_ABI = [
{
"inputs": [
{
"internalType": "contract ISuperToken",
"name": "token",
"type": "address",
},
{"internalType": "address", "name": "sender", "type": "address"},
{"internalType": "address", "name": "receiver", "type": "address"},
{"internalType": "bytes", "name": "userData", "type": "bytes"},
],
"name": "deleteFlow",
"outputs": [{"internalType": "bool", "name": "", "type": "bool"}],
"stateMutability": "nonpayable",
"type": "function",
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""Schema definitions for Superfluid action provider."""

from pydantic import BaseModel, Field


class CreateFlowInput(BaseModel):
"""Input argument schema for creating a flow."""

recipient: str = Field(..., description="The wallet address of the recipient")
token_address: str = Field(..., description="The address of the token that will be streamed")
flow_rate: str = Field(..., description="The flow rate of tokens in wei per second")


class DeleteFlowInput(BaseModel):
"""Input argument schema for deleting a flow."""

recipient: str = Field(..., description="The wallet address of the recipient")
token_address: str = Field(..., description="The address of the token being flowed")


class UpdateFlowInput(BaseModel):
"""Input argument schema for updating a flow."""

recipient: str = Field(..., description="The wallet address of the recipient")
token_address: str = Field(..., description="The address of the token that is being streamed")
new_flow_rate: str = Field(..., description="The new flow rate of tokens in wei per second")
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
from typing import Any

from web3 import Web3

from ...network import Network
from ...wallet_providers import EvmWalletProvider
from ..action_decorator import create_action
from ..action_provider import ActionProvider
from .constants import CREATE_ABI, DELETE_ABI, SUPERFLUID_HOST_ADDRESS, UPDATE_ABI
from .schemas import CreateFlowInput, DeleteFlowInput, UpdateFlowInput


class SuperfluidActionProvider(ActionProvider[EvmWalletProvider]):
"""Provides actions for interacting with Superfluid protocol."""

def __init__(self):
super().__init__("superfluid", [])

@create_action(
name="create_flow",
description="""
This tool will create a money flow to a specified token recipient using Superfluid. Do not use this tool for any other purpose, or trading other assets.
Inputs:
- Wallet address to send the tokens to
- Super token contract address
- The flowrate of flow in wei per second
Important notes:
- The token must be a Superfluid Super token. If errors occur, confirm that the token is a valid Superfluid Super token.
- The flowrate cannot have any decimal points, since the unit of measurement is wei per second.
- Make sure to use the exact amount provided, and if there's any doubt, check by getting more information before continuing with the action.
- 1 wei = 0.000000000000000001 ETH""",
schema=CreateFlowInput,
)
def create_flow(self, wallet_provider: EvmWalletProvider, args: dict[str, Any]) -> str:
"""Create a money flow using Superfluid."""
try:
superfluid_host_contract = Web3().eth.contract(
address=SUPERFLUID_HOST_ADDRESS, abi=CREATE_ABI
)

encoded_data = superfluid_host_contract.encode_abi(
"createFlow",
args=[
args["token_address"],
wallet_provider.get_address(),
args["recipient"],
int(args["flow_rate"]),
"0x",
],
)

params = {"to": SUPERFLUID_HOST_ADDRESS, "data": encoded_data}

tx_hash = wallet_provider.send_transaction(params)

wallet_provider.wait_for_transaction_receipt(tx_hash)

return f"Flow created successfully. Transaction hash: {tx_hash}"

except Exception as e:
return f"Error creating flow: {e!s}"

@create_action(
name="update_flow",
description="""
This tool will update an existing money flow to a specified token recipient using Superfluid. Do not use this tool for any other purpose, or trading other assets.
Inputs:
- Wallet address that the tokens are being streamed to
- Super token contract address
- The new flowrate of flow in wei per second
Important notes:
- The flowrate cannot have any decimal points, since the unit of measurement is wei per second.
- Make sure to use the exact amount provided, and if there's any doubt, check by getting more information before continuing with the action.
- 1 wei = 0.000000000000000001 ETH""",
schema=UpdateFlowInput,
)
def update_flow(self, wallet_provider: EvmWalletProvider, args: dict[str, Any]) -> str:
"""Update an existing money flow using Superfluid."""
try:
superfluid_host_contract = Web3().eth.contract(
address=SUPERFLUID_HOST_ADDRESS, abi=UPDATE_ABI
)

encoded_data = superfluid_host_contract.encode_abi(
"updateFlow",
args=[
args["token_address"],
wallet_provider.get_address(),
args["recipient"],
int(args["new_flow_rate"]),
"0x",
],
)

params = {"to": SUPERFLUID_HOST_ADDRESS, "data": encoded_data}

tx_hash = wallet_provider.send_transaction(params)

wallet_provider.wait_for_transaction_receipt(tx_hash)

return f"Flow updated successfully. Transaction hash: {tx_hash}"

except Exception as e:
return f"Error updating flow: {e!s}"

@create_action(
name="delete_flow",
description="""
This tool will delete an existing money flow to a token recipient using Superfluid. Do not use this tool for any other purpose, or trading other assets.
Inputs:
- Wallet address that the tokens are being streamed to or being streamed from
- Super token contract address""",
schema=DeleteFlowInput,
)
def delete_flow(self, wallet_provider: EvmWalletProvider, args: dict[str, Any]) -> str:
"""Delete an existing money flow using Superfluid."""
try:
superfluid_host_contract = Web3().eth.contract(
address=SUPERFLUID_HOST_ADDRESS, abi=DELETE_ABI
)

encoded_data = superfluid_host_contract.encode_abi(
"deleteFlow",
args=[
args["token_address"],
wallet_provider.get_address(),
args["recipient"],
"0x",
],
)

params = {"to": SUPERFLUID_HOST_ADDRESS, "data": encoded_data}

tx_hash = wallet_provider.send_transaction(params)

wallet_provider.wait_for_transaction_receipt(tx_hash)

return f"Flow deleted successfully. Transaction hash: {tx_hash}"

except Exception as e:
return f"Error deleting flow: {e!s}"

def supports_network(self, network: Network) -> bool:
"""Check if network is supported by Superfluid actions.
Args:
network: The network to check support for.
Returns:
bool: True if the network is supported, False otherwise.
"""
return network.protocol_family == "evm"


def superfluid_action_provider() -> SuperfluidActionProvider:
"""Create a new SuperfluidActionProvider instance."""
return SuperfluidActionProvider()
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def _prepare_transaction(self, transaction: TxParams) -> TxParams:
transaction["to"] = b""

transaction["from"] = self._address
transaction["value"] = int(transaction["value"])
transaction["value"] = int(transaction.get("value", 0))
transaction["type"] = 2
transaction["chainId"] = self._network.chain_id

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ def sign_message(self, message: str | bytes) -> HexStr:
pass

@abstractmethod
def sign_typed_data(
self, typed_data: dict[str, Any]
) -> HexStr:
def sign_typed_data(self, typed_data: dict[str, Any]) -> HexStr:
"""Sign typed data according to EIP-712 standard."""
pass

Expand Down
Loading

0 comments on commit ee1153c

Please sign in to comment.