-
Notifications
You must be signed in to change notification settings - Fork 163
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add Superfluid plugin for Python SDK (#223)
* feat: Add Superfluid plugin for Python SDK\n\n- Implement Superfluid plugin matching TypeScript functionality\n- Add flow management and pool operations\n- Fix Web3EVMWalletClient transaction hash handling\n- Include comprehensive parameter validation Co-Authored-By: Agus Armellini Fischer <[email protected]> * Delete python/src/plugins/superfluid/__init__.py * Update wallet.py * Remove additional flow validations and approvals to match TypeScript exactly Co-Authored-By: Agus Armellini Fischer <[email protected]> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Agus Armellini Fischer <[email protected]> Co-authored-by: Agus <[email protected]>
- Loading branch information
1 parent
035fe58
commit 3cbe996
Showing
7 changed files
with
827 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Superfluid Plugin for GOAT SDK | ||
|
||
This plugin provides integration with Superfluid Protocol for the GOAT SDK, enabling token streaming and pool management capabilities. | ||
|
||
## Features | ||
|
||
- Create, update, or delete token streams | ||
- Get flow rates between addresses | ||
- Manage pool memberships | ||
- Query pool statistics | ||
|
||
## Installation | ||
|
||
```bash | ||
poetry add goat-sdk-plugin-superfluid | ||
``` | ||
|
||
## Usage | ||
|
||
```python | ||
from goat_plugins.superfluid import superfluid, SuperfluidPluginOptions | ||
|
||
# Initialize the plugin | ||
plugin = superfluid() | ||
``` | ||
|
||
## Tools | ||
|
||
The plugin provides the following tools: | ||
|
||
- `flow`: Create, update, or delete a flow of tokens | ||
- `get_flowrate`: Get the current flowrate between addresses | ||
- `update_member_units`: Update units for a pool member | ||
- `get_units`: Get units of a pool member | ||
- `get_member_flow_rate`: Get flow rate of a pool member | ||
- `get_total_flow_rate`: Get total flow rate of a pool |
36 changes: 36 additions & 0 deletions
36
python/src/plugins/superfluid/goat_plugins/superfluid/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
from dataclasses import dataclass | ||
from typing import Optional | ||
|
||
from goat.classes.plugin_base import PluginBase | ||
from goat.types.chain import Chain | ||
from .service import SuperfluidService | ||
|
||
|
||
@dataclass | ||
class SuperfluidPluginOptions: | ||
""" | ||
Configuration options for the Superfluid plugin. | ||
Currently no configuration is needed. | ||
""" | ||
pass | ||
|
||
|
||
class SuperfluidPlugin(PluginBase): | ||
def __init__(self, options: Optional[SuperfluidPluginOptions] = None): | ||
super().__init__("superfluid", [SuperfluidService()]) | ||
|
||
def supports_chain(self, chain: Chain) -> bool: | ||
return chain["type"] == "evm" | ||
|
||
|
||
def superfluid(options: Optional[SuperfluidPluginOptions] = None) -> SuperfluidPlugin: | ||
""" | ||
Create a new instance of the Superfluid plugin. | ||
Args: | ||
options: Optional configuration options for the plugin | ||
Returns: | ||
A configured SuperfluidPlugin instance | ||
""" | ||
return SuperfluidPlugin(options) |
155 changes: 155 additions & 0 deletions
155
python/src/plugins/superfluid/goat_plugins/superfluid/abi.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
CFA_FORWARDER_ABI = [ | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "contract ISuperfluid", | ||
"name": "host", | ||
"type": "address", | ||
}, | ||
], | ||
"stateMutability": "nonpayable", | ||
"type": "constructor", | ||
}, | ||
{"inputs": [], "name": "CFA_FWD_INVALID_FLOW_RATE", "type": "error"}, | ||
{ | ||
"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", | ||
}, | ||
{ | ||
"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", | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "contract ISuperToken", | ||
"name": "token", | ||
"type": "address", | ||
}, | ||
{"internalType": "address", "name": "sender", "type": "address"}, | ||
{"internalType": "address", "name": "receiver", "type": "address"}, | ||
], | ||
"name": "getFlowrate", | ||
"outputs": [{"internalType": "int96", "name": "flowrate", "type": "int96"}], | ||
"stateMutability": "view", | ||
"type": "function", | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "contract ISuperToken", | ||
"name": "token", | ||
"type": "address", | ||
}, | ||
{"internalType": "address", "name": "receiver", "type": "address"}, | ||
{"internalType": "int96", "name": "flowrate", "type": "int96"}, | ||
], | ||
"name": "setFlowrate", | ||
"outputs": [{"internalType": "bool", "name": "", "type": "bool"}], | ||
"stateMutability": "nonpayable", | ||
"type": "function", | ||
}, | ||
] | ||
|
||
POOL_ABI = [ | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "memberAddr", | ||
"type": "address", | ||
}, | ||
{ | ||
"internalType": "uint128", | ||
"name": "newUnits", | ||
"type": "uint128", | ||
}, | ||
], | ||
"name": "updateMemberUnits", | ||
"outputs": [ | ||
{ | ||
"internalType": "bool", | ||
"name": "", | ||
"type": "bool", | ||
}, | ||
], | ||
"stateMutability": "nonpayable", | ||
"type": "function", | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "memberAddr", | ||
"type": "address", | ||
}, | ||
], | ||
"name": "getUnits", | ||
"outputs": [ | ||
{ | ||
"internalType": "uint128", | ||
"name": "", | ||
"type": "uint128", | ||
}, | ||
], | ||
"stateMutability": "view", | ||
"type": "function", | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "memberAddr", | ||
"type": "address", | ||
}, | ||
], | ||
"name": "getMemberFlowRate", | ||
"outputs": [ | ||
{ | ||
"internalType": "int96", | ||
"name": "", | ||
"type": "int96", | ||
}, | ||
], | ||
"stateMutability": "view", | ||
"type": "function", | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "getTotalFlowRate", | ||
"outputs": [ | ||
{ | ||
"internalType": "int96", | ||
"name": "", | ||
"type": "int96", | ||
}, | ||
], | ||
"stateMutability": "view", | ||
"type": "function", | ||
}, | ||
] |
33 changes: 33 additions & 0 deletions
33
python/src/plugins/superfluid/goat_plugins/superfluid/parameters.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
from pydantic import BaseModel, Field | ||
|
||
|
||
class FlowParameters(BaseModel): | ||
token: str = Field(description="The address of the Super Token to get the flow of") | ||
receiver: str = Field(description="The address of the receiver of the flow") | ||
flowrate: str = Field(description="The flowrate of the flow in wei per second (must be a valid int96 value)") | ||
|
||
|
||
class GetFlowrateParameters(BaseModel): | ||
token: str = Field(description="The address of the Super Token to get the flow of") | ||
sender: str = Field(description="The address of the sender of the flow") | ||
receiver: str = Field(description="The address of the receiver of the flow") | ||
|
||
|
||
class UpdateMemberUnitsParameters(BaseModel): | ||
poolAddress: str = Field(description="The address of the Pool contract") | ||
memberAddr: str = Field(description="The address of the member to update units for") | ||
newUnits: int = Field(description="The new units amount for the member") | ||
|
||
|
||
class GetUnitsParameters(BaseModel): | ||
poolAddress: str = Field(description="The address of the Pool contract") | ||
memberAddr: str = Field(description="The address of the member to get units for") | ||
|
||
|
||
class GetMemberFlowRateParameters(BaseModel): | ||
poolAddress: str = Field(description="The address of the Pool contract") | ||
memberAddr: str = Field(description="The address of the member to get flow rate for") | ||
|
||
|
||
class GetTotalFlowRateParameters(BaseModel): | ||
poolAddress: str = Field(description="The address of the Pool contract") |
129 changes: 129 additions & 0 deletions
129
python/src/plugins/superfluid/goat_plugins/superfluid/service.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
from goat.decorators.tool import Tool | ||
from goat_wallets.evm import EVMWalletClient | ||
from .abi import CFA_FORWARDER_ABI, POOL_ABI | ||
from .parameters import ( | ||
FlowParameters, | ||
GetFlowrateParameters, | ||
UpdateMemberUnitsParameters, | ||
GetUnitsParameters, | ||
GetMemberFlowRateParameters, | ||
GetTotalFlowRateParameters, | ||
) | ||
|
||
|
||
class SuperfluidService: | ||
CFA_FORWARDER_ADDRESS = "0xcfA132E353cB4E398080B9700609bb008eceB125" | ||
|
||
@Tool( | ||
{ | ||
"name": "create_or_update_or_delete_flow", | ||
"description": "Create, update, or delete a flow of tokens from sender to receiver", | ||
"parameters_schema": FlowParameters, | ||
} | ||
) | ||
def flow(self, wallet_client: EVMWalletClient, parameters: dict) -> str: | ||
try: | ||
result = wallet_client.send_transaction( | ||
{ | ||
"to": self.CFA_FORWARDER_ADDRESS, | ||
"abi": CFA_FORWARDER_ABI, | ||
"functionName": "setFlowrate", | ||
"args": [parameters["token"], parameters["receiver"], parameters["flowrate"]], | ||
} | ||
) | ||
return result["hash"] | ||
except Exception as error: | ||
raise Exception(f"Failed to set flow: {error}") | ||
|
||
@Tool( | ||
{ | ||
"name": "get_flow_rate", | ||
"description": "Get the current flowrate between a sender and receiver for a specific token", | ||
"parameters_schema": GetFlowrateParameters, | ||
} | ||
) | ||
def get_flowrate(self, wallet_client: EVMWalletClient, parameters: dict): | ||
result = wallet_client.read( | ||
{ | ||
"address": self.CFA_FORWARDER_ADDRESS, | ||
"abi": CFA_FORWARDER_ABI, | ||
"functionName": "getFlowrate", | ||
"args": [parameters["token"], parameters["sender"], parameters["receiver"]], | ||
} | ||
) | ||
return result["value"] | ||
|
||
@Tool( | ||
{ | ||
"name": "update_member_units", | ||
"description": "Update the units for a member in a Superfluid Pool", | ||
"parameters_schema": UpdateMemberUnitsParameters, | ||
} | ||
) | ||
def update_member_units(self, wallet_client: EVMWalletClient, parameters: dict): | ||
try: | ||
hash_result = wallet_client.send_transaction( | ||
{ | ||
"to": parameters["poolAddress"], | ||
"abi": POOL_ABI, | ||
"functionName": "updateMemberUnits", | ||
"args": [parameters["memberAddr"], parameters["newUnits"]], | ||
} | ||
) | ||
return hash_result["hash"] | ||
except Exception as error: | ||
raise Exception(f"Failed to update member units: {error}") | ||
|
||
@Tool( | ||
{ | ||
"name": "get_member_units", | ||
"description": "Get the units of a member in a Superfluid Pool", | ||
"parameters_schema": GetUnitsParameters, | ||
} | ||
) | ||
def get_units(self, wallet_client: EVMWalletClient, parameters: dict): | ||
result = wallet_client.read( | ||
{ | ||
"address": parameters["poolAddress"], | ||
"abi": POOL_ABI, | ||
"functionName": "getUnits", | ||
"args": [parameters["memberAddr"]], | ||
} | ||
) | ||
return result["value"] | ||
|
||
@Tool( | ||
{ | ||
"name": "get_member_flow_rate", | ||
"description": "Get the flow rate of a member in a Superfluid Pool", | ||
"parameters_schema": GetMemberFlowRateParameters, | ||
} | ||
) | ||
def get_member_flow_rate(self, wallet_client: EVMWalletClient, parameters: dict): | ||
result = wallet_client.read( | ||
{ | ||
"address": parameters["poolAddress"], | ||
"abi": POOL_ABI, | ||
"functionName": "getMemberFlowRate", | ||
"args": [parameters["memberAddr"]], | ||
} | ||
) | ||
return result["value"] | ||
|
||
@Tool( | ||
{ | ||
"name": "get_total_flow_rate", | ||
"description": "Get the total flow rate of a Superfluid Pool", | ||
"parameters_schema": GetTotalFlowRateParameters, | ||
} | ||
) | ||
def get_total_flow_rate(self, wallet_client: EVMWalletClient, parameters: dict): | ||
result = wallet_client.read( | ||
{ | ||
"address": parameters["poolAddress"], | ||
"abi": POOL_ABI, | ||
"functionName": "getTotalFlowRate", | ||
"args": [], | ||
} | ||
) | ||
return result["value"] |
Oops, something went wrong.