diff --git a/.eslintrc.base.json b/.eslintrc.base.json
index fc0774380..71005364b 100644
--- a/.eslintrc.base.json
+++ b/.eslintrc.base.json
@@ -6,7 +6,7 @@
"plugin:prettier/recommended",
"plugin:jsdoc/recommended"
],
- "plugins": ["@typescript-eslint", "prettier"],
+ "plugins": ["@typescript-eslint", "prettier", "import"],
"env": {
"node": true,
"es6": true
@@ -16,6 +16,7 @@
"sourceType": "module"
},
"rules": {
+ "import/first": "error",
"multiline-comment-style": ["error", "starred-block"],
"prettier/prettier": "error",
"@typescript-eslint/member-ordering": "error",
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 840199399..b6ca6398a 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
- working-directory: ./cdp-agentkit-core/python
+ working-directory: ./python/cdp-agentkit-core
steps:
- uses: actions/checkout@v3
@@ -26,8 +26,8 @@ jobs:
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
- path: ./cdp-agentkit-core/python/.venv
- key: venv-agentkit-${{ runner.os }}-${{ hashFiles('cdp-agentkit-core/python/poetry.lock') }}
+ path: ./python/cdp-agentkit-core/.venv
+ key: venv-agentkit-${{ runner.os }}-${{ hashFiles('python/cdp-agentkit-core/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
@@ -40,7 +40,7 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
- working-directory: ./cdp-langchain/python
+ working-directory: ./python/cdp-langchain
steps:
- uses: actions/checkout@v3
@@ -60,8 +60,8 @@ jobs:
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
- path: ./cdp-langchain/python/.venv
- key: venv-langchain-${{ runner.os }}-${{ hashFiles('cdp-langchain/python/poetry.lock') }}
+ path: ./python/cdp-langchain/.venv
+ key: venv-langchain-${{ runner.os }}-${{ hashFiles('python/cdp-langchain/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
@@ -74,7 +74,7 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
- working-directory: ./twitter-langchain/python
+ working-directory: ./python/twitter-langchain
steps:
- uses: actions/checkout@v3
@@ -94,8 +94,8 @@ jobs:
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
- path: ./twitter-langchain/python/.venv
- key: venv-twitter-langchain-${{ runner.os }}-${{ hashFiles('twitter-langchain/python/poetry.lock') }}
+ path: ./python/twitter-langchain/.venv
+ key: venv-twitter-langchain-${{ runner.os }}-${{ hashFiles('python/twitter-langchain/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
@@ -104,7 +104,7 @@ jobs:
- name: Run linters
run: poetry run make lint
- lint-cdp-agentkit-core-typescript:
+ lint-agentkit-typescript:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -115,40 +115,7 @@ jobs:
# Install dependencies in parent directory first
- run: npm install
# Then install and lint in working directory
- - name: Install and lint @coinbase/cdp-agentkit-core
- working-directory: ./cdp-agentkit-core/typescript
- run: |
- npm install
- npm run lint
- npm run format
-
- lint-cdp-langchain-typescript:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-node@v4
- with:
- node-version: "18"
- cache: "npm"
- - run: npm install
- - name: Install and lint @coinbase/cdp-langchain
- working-directory: ./cdp-langchain/typescript
- run: |
- npm install
- npm run lint
- npm run format
-
- lint-twitter-langchain-typescript:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-node@v4
- with:
- node-version: "18"
- cache: "npm"
- - run: npm install
- - name: Install and lint @coinbase/twitter-langchain
- working-directory: ./twitter-langchain/typescript
+ - name: Install and lint AgentKit
run: |
npm install
npm run lint
diff --git a/.github/workflows/publish_docs.yml b/.github/workflows/publish_docs.yml
index 95143e80c..0c19c619a 100644
--- a/.github/workflows/publish_docs.yml
+++ b/.github/workflows/publish_docs.yml
@@ -21,20 +21,15 @@ jobs:
npm run build
npm run docs
- - name: Build CDP AgentKit Core JSDocs
+ - name: Build AgentKit JSDocs
run: |
- mkdir -p docs/cdp-agentkit-core/typescript
- cp -r cdp-agentkit-core/typescript/docs/* docs/cdp-agentkit-core/typescript
+ mkdir -p docs/agentkit/typescript
+ cp -r typescript/agentkit/docs/* docs/agentkit/typescript
- - name: Build CDP LangChain JSDocs
+ - name: Build AgentKit LangChain JSDocs
run: |
- mkdir -p docs/cdp-langchain/typescript
- cp -r cdp-langchain/typescript/docs/* docs/cdp-langchain/typescript
-
- - name: Build Twitter LangChain JSDocs
- run: |
- mkdir -p docs/twitter-langchain/typescript
- cp -r twitter-langchain/typescript/docs/* docs/twitter-langchain/typescript
+ mkdir -p docs/agentkit-langchain/typescript
+ cp -r typescript/framework-extensions/langchain/docs/* docs/agentkit-langchain/typescript
- name: Set up Python 3.10
uses: actions/setup-python@v4
@@ -52,73 +47,73 @@ jobs:
id: cached-poetry-dependencies-core
uses: actions/cache@v3
with:
- path: ./cdp-agentkit-core/python/.venv
- key: venv-agentkit-${{ runner.os }}-3.10-${{ hashFiles('cdp-agentkit-core/python/poetry.lock') }}
+ path: ./python/cdp-agentkit-core/.venv
+ key: venv-agentkit-${{ runner.os }}-3.10-${{ hashFiles('python/cdp-agentkit-core/poetry.lock') }}
- name: Install dependencies for CDP AgentKit Core Python
if: steps.cached-poetry-dependencies-core.outputs.cache-hit != 'true'
run: |
- cd cdp-agentkit-core/python
+ cd python/cdp-agentkit-core
poetry install --with dev
cd ..
- name: Build Sphinx Documentation for CDP AgentKit Core Python
run: |
- cd cdp-agentkit-core/python
+ cd python/cdp-agentkit-core
poetry run make docs
cd docs
poetry run make html
cd ../../..
mkdir -p docs/cdp-agentkit-core/python
- cp -r cdp-agentkit-core/python/docs/_build/html/* docs/cdp-agentkit-core/python
+ cp -r python/cdp-agentkit-core/docs/_build/html/* docs/cdp-agentkit-core/python
- name: Load cached venv for CDP LangChain Python
id: cached-poetry-dependencies-langchain
uses: actions/cache@v3
with:
- path: ./cdp-langchain/python/.venv
- key: venv-langchain-${{ runner.os }}-3.10-${{ hashFiles('cdp-langchain/python/poetry.lock') }}
+ path: ./python/cdp-langchain/.venv
+ key: venv-langchain-${{ runner.os }}-3.10-${{ hashFiles('python/cdp-langchain/poetry.lock') }}
- name: Install dependencies for CDP LangChain Python
if: steps.cached-poetry-dependencies-langchain.outputs.cache-hit != 'true'
run: |
- cd cdp-langchain/python
+ cd python/cdp-langchain
poetry install --with dev
cd ..
- name: Build Sphinx Documentation for CDP LangChain Python
run: |
- cd cdp-langchain/python
+ cd python/cdp-langchain
poetry run make docs
cd docs
poetry run make html
cd ../../..
mkdir -p docs/cdp-langchain/python
- cp -r cdp-langchain/python/docs/_build/html/* docs/cdp-langchain/python
+ cp -r python/cdp-langchain/docs/_build/html/* docs/cdp-langchain/python
- name: Load cached venv for Twitter LangChain Python
id: cached-poetry-dependencies-twitter-langchain
uses: actions/cache@v3
with:
- path: ./twitter-langchain/python/.venv
- key: venv-twitter-langchain-${{ runner.os }}-3.10-${{ hashFiles('twitter-langchain/python/poetry.lock') }}
+ path: ./python/twitter-langchain/.venv
+ key: venv-twitter-langchain-${{ runner.os }}-3.10-${{ hashFiles('python/twitter-langchain/poetry.lock') }}
- name: Install dependencies for Twitter LangChain Python
if: steps.cached-poetry-dependencies-twitter-langchain.outputs.cache-hit != 'true'
run: |
- cd twitter-langchain/python
+ cd python/twitter-langchain
poetry install --with dev
cd ..
- name: Build Sphinx Documentation for Twitter LangChain Python
run: |
- cd twitter-langchain/python
+ cd python/twitter-langchain
poetry run make docs
cd docs
poetry run make html
cd ../../..
mkdir -p docs/twitter-langchain/python
- cp -r twitter-langchain/python/docs/_build/html/* docs/twitter-langchain/python
+ cp -r python/twitter-langchain/docs/_build/html/* docs/twitter-langchain/python
- name: Deploy to Github Pages
uses: peaceiris/actions-gh-pages@v4
diff --git a/.github/workflows/publish_npm_cdp_agentkit_core.yml b/.github/workflows/publish_npm_agentkit.yml
similarity index 71%
rename from .github/workflows/publish_npm_cdp_agentkit_core.yml
rename to .github/workflows/publish_npm_agentkit.yml
index d61fd7c51..022aa26fd 100644
--- a/.github/workflows/publish_npm_cdp_agentkit_core.yml
+++ b/.github/workflows/publish_npm_agentkit.yml
@@ -1,10 +1,10 @@
-name: Release CDP AgentKit Core to NPM
+name: Release AgentKit to NPM
on:
workflow_dispatch:
jobs:
- deploy-npm-cdp-agentkit-core:
+ deploy-npm-agentkit:
runs-on: ubuntu-latest
permissions:
contents: read
@@ -16,8 +16,8 @@ jobs:
node-version: "18"
registry-url: "https://registry.npmjs.org"
- run: npm ci
- - name: Install, build and publish @coinbase/cdp-agentkit-core
- working-directory: ./cdp-agentkit-core/typescript
+ - name: Install, build and publish @coinbase/agentkit
+ working-directory: ./typescript/agentkit
run: |
npm ci
npm run build
diff --git a/.github/workflows/publish_npm_farcaster_langchain.yml b/.github/workflows/publish_npm_agentkit_langchain.yml
similarity index 70%
rename from .github/workflows/publish_npm_farcaster_langchain.yml
rename to .github/workflows/publish_npm_agentkit_langchain.yml
index a531a789d..bddd6bde9 100644
--- a/.github/workflows/publish_npm_farcaster_langchain.yml
+++ b/.github/workflows/publish_npm_agentkit_langchain.yml
@@ -1,10 +1,10 @@
-name: Publish Farcaster LangChain to NPM
+name: Publish AgentKit LangChain to NPM
on:
workflow_dispatch:
jobs:
- deploy-npm-farcaster-langchain:
+ deploy-npm-agentkit-langchain:
runs-on: ubuntu-latest
permissions:
contents: read
@@ -16,8 +16,8 @@ jobs:
node-version: "18"
registry-url: "https://registry.npmjs.org"
- run: npm i && npm run build
- - name: Install, build and publish @coinbase/farcaster-langchain
- working-directory: ./farcaster-langchain/typescript
+ - name: Install, build and publish @coinbase/agentkit-langchain
+ working-directory: ./typescript/framework-extensions/langchain
run: |
npm publish --ignore-scripts --provenance --access public
env:
diff --git a/.github/workflows/publish_npm_cdp_langchain.yml b/.github/workflows/publish_npm_cdp_langchain.yml
deleted file mode 100644
index d37cc98e5..000000000
--- a/.github/workflows/publish_npm_cdp_langchain.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-name: Publish CDP LangChain to NPM
-
-on:
- workflow_dispatch:
-
-jobs:
- deploy-npm-cdp-langchain:
- runs-on: ubuntu-latest
- permissions:
- contents: read
- id-token: write
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-node@v4
- with:
- node-version: "18"
- registry-url: "https://registry.npmjs.org"
- - run: npm i && npm run build
- - name: Install, build and publish @coinbase/cdp-langchain
- working-directory: ./cdp-langchain/typescript
- run: |
- npm publish --ignore-scripts --provenance --access public
- env:
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.github/workflows/publish_npm_twitter_langchain.yml b/.github/workflows/publish_npm_twitter_langchain.yml
deleted file mode 100644
index 1a3d91972..000000000
--- a/.github/workflows/publish_npm_twitter_langchain.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-name: Publish Twitter LangChain to NPM
-
-on:
- workflow_dispatch:
-
-jobs:
- deploy-npm-twitter-langchain:
- runs-on: ubuntu-latest
- permissions:
- contents: read
- id-token: write
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-node@v4
- with:
- node-version: "18"
- registry-url: "https://registry.npmjs.org"
- - run: npm i && npm run build
- - name: Install, build and publish @coinbase/twitter-langchain
- working-directory: ./twitter-langchain/typescript
- run: |
- npm publish --ignore-scripts --provenance --access public
- env:
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.github/workflows/publish_pypi_cdp_agentkit_core.yml b/.github/workflows/publish_pypi_cdp_agentkit_core.yml
index c8a6ac723..a402a032c 100644
--- a/.github/workflows/publish_pypi_cdp_agentkit_core.yml
+++ b/.github/workflows/publish_pypi_cdp_agentkit_core.yml
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
- working-directory: ./cdp-agentkit-core/python
+ working-directory: ./python/cdp-agentkit-core
environment:
name: pypi
url: https://pypi.org/p/cdp-agentkit-core
@@ -41,4 +41,4 @@ jobs:
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
- packages-dir: cdp-agentkit-core/python/dist/
+ packages-dir: python/cdp-agentkit-core/dist/
diff --git a/.github/workflows/publish_pypi_cdp_langchain.yml b/.github/workflows/publish_pypi_cdp_langchain.yml
index 2ab26d471..215c3cedf 100644
--- a/.github/workflows/publish_pypi_cdp_langchain.yml
+++ b/.github/workflows/publish_pypi_cdp_langchain.yml
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
- working-directory: ./cdp-langchain/python
+ working-directory: ./python/cdp-langchain
environment:
name: pypi
url: https://pypi.org/p/cdp-langchain
@@ -41,4 +41,4 @@ jobs:
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
- packages-dir: cdp-langchain/python/dist/
+ packages-dir: python/cdp-langchain/dist/
diff --git a/.github/workflows/publish_pypi_twitter_langchain.yml b/.github/workflows/publish_pypi_twitter_langchain.yml
index 92834c1b5..5a08d6eef 100644
--- a/.github/workflows/publish_pypi_twitter_langchain.yml
+++ b/.github/workflows/publish_pypi_twitter_langchain.yml
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
- working-directory: ./twitter-langchain/python
+ working-directory: ./python/twitter-langchain
environment:
name: pypi
url: https://pypi.org/p/twitter-langchain
@@ -41,4 +41,4 @@ jobs:
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
- packages-dir: twitter-langchain/python/dist/
+ packages-dir: python/twitter-langchain/dist/
diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml
index b2d124167..2e003ab2b 100644
--- a/.github/workflows/unit_tests.yml
+++ b/.github/workflows/unit_tests.yml
@@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
- working-directory: ./cdp-agentkit-core/python
+ working-directory: ./python/cdp-agentkit-core
strategy:
matrix:
python: ['3.10', '3.11', '3.12']
@@ -30,8 +30,8 @@ jobs:
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
- path: ./cdp-agentkit-core/python/.venv
- key: venv-agentkit-${{ runner.os }}-${{ matrix.python }}-${{ hashFiles('cdp-agentkit-core/python/poetry.lock') }}
+ path: ./python/cdp-agentkit-core/.venv
+ key: venv-agentkit-${{ runner.os }}-${{ matrix.python }}-${{ hashFiles('python/cdp-agentkit-core/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
@@ -44,7 +44,7 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
- working-directory: ./cdp-langchain/python
+ working-directory: ./python/cdp-langchain
strategy:
matrix:
python: ['3.10', '3.11', '3.12']
@@ -68,8 +68,8 @@ jobs:
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
- path: ./cdp-langchain/python/.venv
- key: venv-langchain-${{ runner.os }}-${{ matrix.python }}-${{ hashFiles('cdp-langchain/python/poetry.lock') }}
+ path: ./python/cdp-langchain/.venv
+ key: venv-langchain-${{ runner.os }}-${{ matrix.python }}-${{ hashFiles('python/cdp-langchain/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
@@ -82,7 +82,7 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
- working-directory: ./twitter-langchain/python
+ working-directory: ./python/twitter-langchain
strategy:
matrix:
python: ['3.10', '3.11', '3.12']
@@ -106,8 +106,8 @@ jobs:
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
- path: ./twitter-langchain/python/.venv
- key: venv-twitter-langchain-${{ runner.os }}-${{ matrix.python }}-${{ hashFiles('cdp-twitter-langchain/python/poetry.lock') }}
+ path: ./python/twitter-langchain/.venv
+ key: venv-twitter-langchain-${{ runner.os }}-${{ matrix.python }}-${{ hashFiles('python/twitter-langchain/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
diff --git a/CONTRIBUTING-PYTHON.md b/CONTRIBUTING-PYTHON.md
index 3b6aa15f7..82b9d6530 100644
--- a/CONTRIBUTING-PYTHON.md
+++ b/CONTRIBUTING-PYTHON.md
@@ -6,7 +6,7 @@ This guide covers Python-specific setup and development for AgentKit.
- [Development Setup](#development-setup)
- [Adding an Agentic Action](#adding-an-agentic-action)
-- [Adding an Agentic Action to Langchain Toolkit](#adding-an-agentic-action-to-langchain-toolkit)
+- [Adding an Agentic Action to LangChain Toolkit](#adding-an-agentic-action-to-langchain-toolkit)
- [Adding an Agentic Action to the Twitter Toolkit](#adding-an-agentic-action-to-the-twitter-toolkit)
- [Integrating into an AI Agent Framework](#integrating-into-an-ai-agent-framework)
- [Testing](#testing)
@@ -37,12 +37,12 @@ An Action is an interface for an AI Agent to interact with the real world: any P
2. **Input Schema**: Define the input parameters using [Pydantic](https://docs.pydantic.dev/latest/) schemas. Pydantic is used to validate the inputs to the action and to generate a JSON schema that can be used by the LLM to understand the inputs.
3. **Implementation Function**: The actual logic that executes the action. This function receives as input the wallet that the Agent has access to, and as you'll see in the walkthrough below, we can use this wallet to invoke an onchain contract! For more information on contract invocations using a CDP wallet, see [here](https://docs.cdp.coinbase.com/cdp-sdk/docs/onchain-interactions#smart-contract-interactions).
-In practice, Actions are housed in `cdp-agentkit-core/python/cdp_agentkit_core/actions` and generally grouped by the type of action they are. For example, actions related to interacting with social platforms such as X (Twitter) are housed in `cdp-agentkit-core/python/cdp_agentkit_core/actions/social/twitter`. When adding a new action, check if there is an existing folder for the type of action you are adding and add your new action to the appropriate folder.
+In practice, Actions are housed in `python/cdp-agentkit-core/cdp_agentkit_core/actions` and generally grouped by the type of action they are. For example, actions related to interacting with social platforms such as X (Twitter) are housed in `python/cdp-agentkit-core/cdp_agentkit_core/actions/social/twitter`. When adding a new action, check if there is an existing folder for the type of action you are adding and add your new action to the appropriate folder.
Here's the structure of the actions directory:
```
-./cdp-agentkit-core/python
+./python/cdp-agentkit-core
└── cdp_agentkit_core
└── actions
├── defi
@@ -53,7 +53,7 @@ Here's the structure of the actions directory:
└── wow
```
-Once you decide which folder to add your action to, go ahead and create a new file there to house your action, then read through the following sections to learn how to implement your action. For a complete example of an action, see [mint_nft.py](https://github.com/coinbase/agentkit/blob/master/cdp-agentkit-core/python/cdp_agentkit_core/actions/mint_nft.py).
+Once you decide which folder to add your action to, go ahead and create a new file there to house your action, then read through the following sections to learn how to implement your action. For a complete example of an action, see [mint_nft.py](https://github.com/coinbase/agentkit/blob/master/python/cdp-agentkit-core/cdp_agentkit_core/actions/mint_nft.py).
### Crafting a good prompt
@@ -136,30 +136,30 @@ class MintNftAction(CdpAction):
func: Callable[..., str] = mint_nft
```
-This class is then exported out of [`cdp_agentkit_core/actions/__init__.py`](https://github.com/coinbase/agentkit/blob/master/cdp-agentkit-core/python/cdp_agentkit_core/actions/__init__.py) so that is is consumable by users of the `cdp-agentkit-core` package.
+This class is then exported out of [`cdp_agentkit_core/actions/__init__.py`](https://github.com/coinbase/agentkit/blob/master/python/cdp-agentkit-core/cdp_agentkit_core/actions/__init__.py) so that is is consumable by users of the `cdp-agentkit-core` package.
### Testing the action
There are two forms of testing you should do: unit testing and manual end-to-end testing.
-To add a unit test for your action, add a file to the folder in `cdp-agentkit-core/python/tests/actions` that corresponds to the same folder that you are adding your action to. For an example, see [test_mint_nft.py](https://github.com/coinbase/agentkit/blob/master/cdp-agentkit-core/python/tests/actions/test_mint_nft.py).
+To add a unit test for your action, add a file to the folder in `python/cdp-agentkit-core/tests/actions` that corresponds to the same folder that you are adding your action to. For an example, see [test_mint_nft.py](https://github.com/coinbase/agentkit/blob/master/python/cdp-agentkit-core/tests/actions/test_mint_nft.py).
You can then run the unit tests with the following command:
```bash
-cd cdp-agentkit-core/python
+cd python/cdp-agentkit-core
make test
```
For instructions on manual end-to-end testing, see the [Testing](#testing) section.
-## Adding an Agentic Action to Langchain Toolkit
+## Adding an Agentic Action to LangChain Toolkit
-The action will be included automatically, all you need to do is add the action to the list of tools in the `CdpToolkit` class documentation in `cdp-langchain/python/cdp_langchain/agent_toolkits/cdp_toolkit.py`.
+The action will be included automatically, all you need to do is add the action to the list of tools in the `CdpToolkit` class documentation in `python/cdp-langchain/cdp_langchain/agent_toolkits/cdp_toolkit.py`.
## Adding an Agentic Action to the Twitter Toolkit
1. Ensure the action is implemented in `cdp-agentkit-core/actions/social/twitter`.
-2. Add a wrapper method to `TwitterApiWrapper` in `./twitter_langchain/twitter_api_wrapper.py`
+2. Add a wrapper method to `TwitterApiWrapper` in `python/twitter-langchain/twitter_langchain/twitter_api_wrapper.py`
- E.g.
```python
def post_tweet_wrapper(self, tweet: str) -> str:
@@ -176,14 +176,14 @@ The action will be included automatically, all you need to do is add the action
return post_tweet(client=self.client, tweet=tweet)
```
-3. Add call to the wrapper in `TwitterApiWrapper.run` in `./twitter_langchain/twitter_api_wrapper.py`
+3. Add call to the wrapper in `TwitterApiWrapper.run` in `python/twitter-langchain/twitter_langchain/twitter_api_wrapper.py`
- E.g.
```python
if mode == "post_tweet":
return self.post_tweet_wrapper(**kwargs)
```
-4. Add the action to the list of available tools in the `TwitterToolkit` in `./twitter_langchain/twitter_toolkit.py`
+4. Add the action to the list of available tools in the `TwitterToolkit` in `python/twitter-langchain/twitter_langchain/twitter_toolkit.py`
- E.g.
```python
actions: List[Dict] = [
@@ -205,21 +205,21 @@ Actions are necessary building blocks powering onchain AI applications, but they
Integrations into AI Agent frameworks are specific to the framework itself, so we can't go into specific implementation details here, but we can offer up some examples and tips.
- To automatically get access to new actions as they are released, make sure to import the `CDP_ACTIONS` constant from `cdp-agentkit-core`. This will make it so that all you / the framework authors have to do to get new actions is bump the version of AgentKit the framework is using.
-- Check out how [AgentKit Actions are mapped into LangChain Tools](https://github.com/coinbase/agentkit/blob/master/cdp-langchain/python/cdp_langchain/agent_toolkits/cdp_toolkit.py#L132-L141)
+- Check out how [AgentKit Actions are mapped into LangChain Tools](https://github.com/coinbase/agentkit/blob/master/python/cdp-langchain/cdp_langchain/agent_toolkits/cdp_toolkit.py#L132-L141)
## Testing
### Local Testing
-A good way to test new actions locally is by using the chatbot example in `cdp-langchain`. See the [chatbot README](https://github.com/coinbase/agentkit/blob/master/cdp-langchain/examples/chatbot-python/README.md) for instructions on setting up and running the chatbot.
+A good way to test new actions locally is by using the chatbot example in `cdp-langchain`. See the [chatbot README](https://github.com/coinbase/agentkit/blob/master/python/examples/cdp-langchain-chatbot/README.md) for instructions on setting up and running the chatbot.
The flow is:
1. Make your change as described in the [Adding an Agentic Action](#adding-an-agentic-action) section
-2. Update `cdp-langchain/examples/chatbot-python/pyproject.toml` to point to the local package
+2. Update `python/examples/cdp-langchain-chatbot/pyproject.toml` to point to the local package
```diff
[tool.poetry]
-name = "chatbot-python"
+name = "cdp-langchain-chatbot"
version = "0.0.1"
description = "CDP AgentKit Example Chatbot"
authors = ["John Peterson "]
@@ -229,13 +229,13 @@ package-mode = false
[tool.poetry.dependencies]
python = "^3.10"
- cdp-langchain = "^0.0.11"
-+ cdp-langchain = { path: "../../cdp-agentkit-core/python", develop: true }
++ cdp-langchain = { path: "../cdp-agentkit-core", develop: true }
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
```
-3. In `cdp-langchain/examples/chatbot-python`, run `python chatbot.py`
+3. In `python/examples/cdp-langchain-chatbot`, run `python chatbot.py`
4. You can now interact with your new action via the chatbot!
### Running Unit Tests
@@ -246,9 +246,9 @@ From the package you are working in, you can run:
make test
```
-For example, to run all tests in the `cdp_agentkit_core` package, you can run:
+For example, to run all tests in the `cdp-agentkit-core` package, you can run:
```bash
-cd cdp-agentkit-core/python
+cd python/cdp-agentkit-core
make test
```
diff --git a/CONTRIBUTING-TYPESCRIPT.md b/CONTRIBUTING-TYPESCRIPT.md
index a543a622c..5b618f7a2 100644
--- a/CONTRIBUTING-TYPESCRIPT.md
+++ b/CONTRIBUTING-TYPESCRIPT.md
@@ -5,8 +5,8 @@ This guide covers TypeScript-specific setup and development for AgentKit.
## Contents
- [Development Setup](#development-setup)
-- [Adding an Agentic Action](#adding-an-agentic-action)
-- [Adding an Agentic Action to Langchain Toolkit](#adding-an-agentic-action-to-langchain-toolkit)
+- [Adding an Action Provider](#adding-an-action-provider)
+- [Adding a Wallet Provider](#adding-a-wallet-provider)
- [Integrating into an AI Agent Framework](#integrating-into-an-ai-agent-framework)
- [Testing](#testing)
- [Code Style](#code-style)
@@ -26,36 +26,52 @@ If the versions are not correct or you don't have Node.js or npm installed, down
Once you have these installed, make sure you install the project dependencies by running `npm install` from the root of the repository.
-## Adding an Agentic Action
+## Adding an Action Provider
-An Action is an interface for an AI Agent to interact with the real world: any TypeScript function that you can think of can be used by an Agent via an Action! There are a few components to an Action:
+An Action is an interface for an AI Agent to interact with the real world: any TypeScript function that you can think of can be used by an Agent via an Action! Actions are grouped by Action Providers, which are classes that contain a collection of actions along with configuration and helper functions.
-1. **Prompt**: A description that helps the AI understand when and how to use the action. It's important to describe the inputs and outputs of the action and include examples. Additionally, think about what inputs can be removed entirely and fetched or inferred by the LLM, so that users don't have to manually provide them.
-2. **Input Schema**: Define the input parameters using [Zod](https://zod.dev/) schemas. Zod is used to validate the inputs to the action and to generate a JSON schema that can be used by the LLM to understand the inputs.
-3. **Implementation Function**: The actual logic that executes the action. This function receives as input the wallet that the Agent has access to, and as you'll see in the walkthrough below, we can use this wallet to invoke an onchain contract! For more information on contract invocations using a CDP wallet, see [here](https://docs.cdp.coinbase.com/cdp-sdk/docs/onchain-interactions#smart-contract-interactions).
+Action Components:
-In practice, Actions are housed in `cdp-agentkit-core/typescript/src/actions/cdp` and generally grouped by the type of action they are. For example, actions related to interacting with social platforms such as X (Twitter) are housed in `cdp-agentkit-core/typescript/src/actions/cdp/social/twitter`. When adding a new action, check if there is an existing folder for the type of action you are adding and add your new action to the appropriate folder.
+1. **Name**: The name of the action. This is used to identify the action when it is added to an Agent.
-Here's the structure of the actions directory:
+2. **Description**: A description that helps the AI understand when and how to use the action. It's important to describe the inputs and outputs of the action and include examples. Additionally, think about what inputs can be removed entirely and fetched or inferred by the LLM, so that users don't have to manually provide them.
+
+3. **Input Schema**: Define the input parameters using [Zod](https://zod.dev/) schemas. Zod is used to validate the inputs to the action and to generate a JSON schema that can be used by the LLM to understand the inputs.
+
+4. **Invocation Function**: The actual logic that executes the action. This function receives as input the wallet that the Agent has access to, and as you'll see in the walkthrough below, we can use this wallet to invoke an onchain contract! For more information on contract invocations using a CDP wallet, see [here](https://docs.cdp.coinbase.com/cdp-sdk/docs/onchain-interactions#smart-contract-interactions).
+
+In practice, action providers are housed in `typescript/agentkit/src/action-providers` and generally grouped by the type of action they are and the configuration they require . For example, actions related to interacting with social platforms such as X (Twitter) are housed in `typescript/agentkit/src/action-providers/twitter`. When adding a new action, check if there is an existing action provider for the type of action you are adding and add your new action to the appropriate folder.
+
+Here's the structure of the action providers directory:
```
-./cdp-agentkit-core/typescript/src
-└── actions
- └── cdp
- ├── data
- ├── defi
- └── social
+./typescript/agentkit/src
+└── action-providers
+ └── pyth
+ ├── pythActionProvider.ts
+ ├── schemas.ts
+ └── pythActionProvider.test.ts
+ └── ...
```
-Once you decide which folder to add your action to, go ahead and create a new file there to house your action, then read through the following sections to learn how to implement your action. For a complete example of an action, see [mint_nft.ts](https://github.com/coinbase/agentkit/blob/master/cdp-agentkit-core/typescript/src/actions/cdp/mint_nft.ts).
+Once you decide which folder to add your action to, go ahead and create a new file there to house your action, then read through the following sections to learn how to implement your action. For a complete example of an action provider, see [erc721ActionProvider.ts](https://github.com/coinbase/agentkit/blob/master/typescript/agentkit/src/action-providers/erc721/erc721ActionProvider.ts).
-### Crafting a good prompt
+### Crafting a good description prompt
-The prompt is used by the LLM to understand when and how to use the action. It's important to be as specific as possible in describing the inputs and outputs of the action and include examples. Take the Mint NFT prompt for example:
+The description prompt is used by the LLM to understand when and how to use the action. It's important to be as specific as possible in describing the inputs and outputs of the action and include examples. Take the Mint NFT prompt for example:
```typescript
-const MINT_NFT_PROMPT = `
-This tool will mint an NFT (ERC-721) to a specified destination address onchain via a contract invocation. It takes the contract address of the NFT onchain and the destination address onchain that will receive the NFT as inputs. Do not use the contract address as the destination address. If you are unsure of the destination address, please ask the user before proceeding.`;
+// src/action-providers/erc721/erc721ActionProvider.ts
+
+ @CreateAction({
+ name: "mint",
+ description: `
+This tool will mint an NFT (ERC-721) to a specified destination address onchain via a contract invocation.
+It takes the contract address of the NFT onchain and the destination address onchain that will receive the NFT as inputs.
+Do not use the contract address as the destination address. If you are unsure of the destination address, please ask the user before proceeding.
+`,
+ schema: MintSchema,
+ })
```
* The prompt disambuguates the type of NFT by specifying "ERC-721"
@@ -68,7 +84,9 @@ This tool will mint an NFT (ERC-721) to a specified destination address onchain
The input schema is used to validate the inputs to the action and to generate a JSON schema that can be used by the LLM to understand the inputs. For TypeScript, we use [Zod](https://zod.dev/) to define the input schema. For example, the Mint NFT input schema is defined as follows:
```typescript
-const MintNftInput = z
+// src/action-providers/erc721/schemas.ts
+
+const MintSchema = z
.object({
contractAddress: z.string().describe("The contract address of the NFT to mint"),
destination: z.string().describe("The destination address that will receive the NFT"),
@@ -79,88 +97,124 @@ const MintNftInput = z
This says that the input schema has two fields: `contractAddress` and `destination`. The `contractAddress` field is required and must be a string. The `destination` field is required and must be a string. For more information on Zod, see the [Zod documentation](https://zod.dev/).
-### Implementing the action
-
-Now we need to implement the actual function that the AI will call when using your action. The function receives as input the wallet that the Agent has access to, along with the inputs defined in the input schema, and it must return a string. This return value is used by the LLM to understand the result of the action, which in turn will generate a user-facing response. Here's an example of the Mint NFT implementation function:
+### Implementing the action provider
```typescript
-async function mintNft(wallet: Wallet, args: z.infer): Promise {
- const mintArgs = {
- to: args.destination,
- quantity: "1",
- };
-
- try {
- const mintInvocation = await wallet.invokeContract({
- contractAddress: args.contractAddress,
- method: "mint",
- args: mintArgs,
- });
-
- const result = await mintInvocation.wait();
-
- return `Minted NFT from contract ${args.contractAddress} to address ${args.destination} on network ${wallet.getNetworkId()}.\nTransaction hash for the mint: ${result.getTransaction().getTransactionHash()}\nTransaction link for the mint: ${result.getTransaction().getTransactionLink()}`;
- } catch (error) {
- return `Error minting NFT: ${error}`;
+// src/action-providers/erc721/erc721ActionProvider.ts
+
+export class Erc721ActionProvider extends ActionProvider {
+ constructor() {
+ super("erc721", []);
}
+
+ supportsNetwork = (network: Network) => network.protocolFamily === "evm";
}
+
+export const erc721ActionProvider = () => new Erc721ActionProvider();
```
-Notice the return value contains useful information for the user, such as the transaction hash and link. It's important to include this information in the return value so that the user can easily see the result of the action.
+### Implementing the action
-Finally, we need to create a class that implements the `CdpAction` interface and export it. This class contains the name, description, input schema, and implementation function of the action. Here's an example of the Mint NFT action class:
+Now we need to implement the actual function that the AI will call when using your action. Actions are defined as instance methods on the action provider class with the `@CreateAction` decorator. The function receives as input the wallet provider that the Agent has access to, along with the inputs defined in the input schema, and it must return a string. This return value is used by the LLM to understand the result of the action, which in turn will generate a user-facing response. Here's an example of the Mint NFT implementation instance method:
```typescript
-export class MintNftAction implements CdpAction {
- public name = "mint_nft";
- public description = MINT_NFT_PROMPT;
- public argsSchema = MintNftInput;
- public func = mintNft;
+// src/action-providers/erc721/erc721ActionProvider.ts
+
+export class Erc721ActionProvider extends ActionProvider {
+ constructor() {
+ super("erc721", []);
+ }
+
+ @CreateAction({
+ name: "mint",
+ description: `
+This tool will mint an NFT (ERC-721) to a specified destination address onchain via a contract invocation.
+It takes the contract address of the NFT onchain and the destination address onchain that will receive the NFT as inputs.
+Do not use the contract address as the destination address. If you are unsure of the destination address, please ask the user before proceeding.
+`,
+ schema: MintSchema,
+ })
+ async mint(walletProvider: EvmWalletProvider, args: z.infer): Promise {
+ try {
+ const data = encodeFunctionData({
+ abi: ERC721_ABI,
+ functionName: "mint",
+ args: [args.destination as Hex, 1n],
+ });
+
+ const hash = await walletProvider.sendTransaction({
+ to: args.contractAddress as `0x${string}`,
+ data,
+ });
+
+ await walletProvider.waitForTransactionReceipt(hash);
+
+ return `Successfully minted NFT ${args.contractAddress} to ${args.destination}`;
+ } catch (error) {
+ return `Error minting NFT ${args.contractAddress} to ${args.destination}: ${error}`;
+ }
+ }
+
+ supportsNetwork = (network: Network) => network.protocolFamily === "evm";
}
+
```
-This class is then exported out of [cdp-agentkit-core/typescript/src/actions/cdp/index.ts](https://github.com/coinbase/agentkit/blob/master/cdp-agentkit-core/typescript/src/actions/cdp/index.ts) so that is is consumable by users of the `@coinbase/cdp-agentkit-core` package.
+Notice the return value contains useful information for the user, such as the transaction hash and link. It's important to include this information in the return value so that the user can easily see the result of the action.
-### Testing the action
+This class is then exported out of [typescript/agentkit/src/action-providers/erc721/index.ts](https://github.com/coinbase/agentkit/blob/master/typescript/agentkit/src/action-providers/erc721/index.ts) so that is is consumable by users of the `@coinbase/agentkit` package.
+
+### Testing the action provider
There are two forms of testing you should do: unit testing and manual end-to-end testing.
-To add a unit test for your action, add a file to the folder in `cdp-agentkit-core/typescript/src/tests/actions` that corresponds to the same folder that you are adding your action to, or to the top-level if there is no folder. For an example, see [test_mint_nft.ts](https://github.com/coinbase/agentkit/blob/master/cdp-agentkit-core/typescript/tests/actions/test_mint_nft.ts).
+To add a unit test for your action provider, add a file to your action provider folder post-fixing it with `.test.ts`. For an example, see [pythActionProvider.test.ts](https://github.com/coinbase/agentkit/blob/master/typescript/agentkit/src/action-providers/pyth/pythActionProvider.test.ts).
You can then run the unit tests with the following command:
```bash
-cd cdp-agentkit-core/typescript
+cd typescript/agentkit
npm test
```
For instructions on manual end-to-end testing, see the [Testing](#testing) section.
-Check out the [Testing](#testing) section to learn how to manually test your new action.
+Check out the [Testing](#testing) section to learn how to manually test your new action provider.
+
+## Adding a Wallet Provider
+
+Wallet providers give an agent access to a wallet. AgentKit currently supports the following wallet providers:
+
+EVM:
+- [CdpWalletProvider](https://github.com/coinbase/agentkit/blob/master/typescript/agentkit/src/wallet-providers/cdpWalletProvider.ts)
+- [ViemWalletProvider](https://github.com/coinbase/agentkit/blob/master/typescript/agentkit/src/wallet-providers/viemWalletProvider.ts)
+
+### Adding a new EVM wallet provider
+
+The EVM Wallet Providers are housed in `typescript/agentkit/src/wallet-providers`. EVM Wallet Providers extend `EvmWalletProvider` which is an abstract class that conforms to [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193). To add a new EVM wallet provider, create a new file in the `wallet-providers` directory and implement a class that extends `EvmWalletProvider`.
-## Adding an Agentic Action to Langchain Toolkit
+### Adding a new non-EVM wallet provider
-The action will be included automatically, all you need to do is add the action to the list of tools in the `CdpToolkit` class documentation in `cdp-langchain/typescript/src/toolkits/cdp_toolkit.ts`.
+Non-EVM Wallet Providers are housed in `typescript/agentkit/src/wallet-providers`. Non-EVM Wallet Providers extend `WalletProvider` which is an abstract class that provides a core set of wallet functionality. To add a new non-EVM wallet provider, create a new file in the `wallet-providers` directory and implement a class that extends `WalletProvider`.
## Integrating into an AI Agent Framework
Actions are necessary building blocks powering onchain AI applications, but they're just one piece of the puzzle. To make them truly useful, they must be integrated into an AI Agent framework such as [LangChain](https://www.langchain.com/) or [Eliza](https://elizaos.github.io/eliza/), among others.
Integrations into AI Agent frameworks are specific to the framework itself, so we can't go into specific implementation details here, but we can offer up some examples and tips.
-- To automatically get access to new actions as they are released, make sure to import the `CDP_ACTIONS` constant from `@coinbase/cdp-agentkit-core`. This will make it so that all you / the framework authors have to do to get new actions is bump the version of AgentKit the framework is using.
-- Check out how [AgentKit actions are mapped into LangChain Tools](https://github.com/coinbase/agentkit/blob/master/cdp-langchain/typescript/src/toolkits/cdp_toolkit.ts#L59)
+- Check out how [AgentKit actions are mapped into LangChain Tools](https://github.com/coinbase/agentkit/blob/master/typescript/agentkit-langchain/src/index.ts)
- Check out how [AgentKit Actions are mapped into Eliza Actions](https://github.com/elizaOS/eliza/blob/develop/packages/plugin-agentkit/src/actions.ts#L31)
## Testing
### Local Testing
-A good way to test new actions locally is by using the chatbot example in `cdp-langchain`. See the [chatbot README](https://github.com/coinbase/agentkit/blob/master/cdp-langchain/examples/chatbot-typescript/README.md) for instructions on setting up and running the chatbot.
+A good way to test new actions locally is by using the chatbot example in `typescript/examples/langchain-cdp-chatbot`. See the [chatbot README](https://github.com/coinbase/agentkit/blob/master/typescript/examples/langchain-cdp-chatbot/README.md) for instructions on setting up and running the chatbot.
The flow is:
1. Make your change as described in the [Adding an Agentic Action](#adding-an-agentic-action) section
-2. From root, run `npm run build`
-3. In `cdp-langchain/examples/chatbot-typescript`, run `npm run start`
+2. From root, run `npm run build && npm i`
+3. In `typescript/examples/langchain-cdp-chatbot`, run `npm run start`
4. You can now interact with your new action via the chatbot!
### Running Tests
@@ -171,9 +225,9 @@ From the package you are working in, you can run:
npm test
```
-For example, to run all tests in the `cdp-agentkit-core` package, you can run:
+For example, to run all tests in the `@coinbase/agentkit` package, you can run:
```bash
-cd cdp-agentkit-core/typescript
+cd typescript/agentkit
npm test
```
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c083e4989..01edb8121 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -4,7 +4,7 @@ Thank you for your interest in contributing to AgentKit! We welcome all contribu
## Repository Structure
-The AgentKit repository is organized as a [multi-package workspace](https://vercel.com/docs/vercel-platform/glossary#multi-package-workspace) (otherwise known as a [monorepo](https://vercel.com/docs/vercel-platform/glossary#monorepo)) and managed with [Turborepo](https://turbo.build/repo/docs). The repo contains multiple packages for Python and TypeScript, where a [package](https://vercel.com/docs/vercel-platform/glossary#package) is a single subfolder with either a `package.json` (if it's a TypeScript package) or a `pyproject.toml` (if it's a Python package),and related code that is published to either NPM or PyPI. For example, the `cdp-agentkit-core/typescript` subfolder is one package, and the `cdp-agentkit-core/python` subfolder is another package.
+The AgentKit repository is organized as a [multi-package workspace](https://vercel.com/docs/vercel-platform/glossary#multi-package-workspace) (otherwise known as a [monorepo](https://vercel.com/docs/vercel-platform/glossary#monorepo)) and managed with [Turborepo](https://turbo.build/repo/docs). The repo contains multiple packages for Python and TypeScript, where a [package](https://vercel.com/docs/vercel-platform/glossary#package) is a single subfolder with either a `package.json` (if it's a TypeScript package) or a `pyproject.toml` (if it's a Python package),and related code that is published to either NPM or PyPI. For example, the `typescript/agentkit` subfolder is one package, and the `python/cdp-agentkit-core` subfolder is another package.
Note that not all AgentKit packages have both Python and TypeScript implementations. This is okay, and we expect some level of drift between the languages. If you'd like to add a TypeScript variant of a package that only has a Python variant (or vice versa), that would be a great and welcome contribution!
@@ -12,18 +12,22 @@ See this section for tips on developing in our monorepo: [Monorepo Development T
Here's a high-level overview of the repository structure:
```
-./agentkit
-├── cdp-agentkit-core/
-│ ├── python/
-│ └── typescript/
-├── cdp-langchain/
-│ ├── python/
-│ └── typescript/
-├── farcaster-langchain/
-│ └── typescript/
-└── twitter-langchain/
- ├── python/
- └── typescript/
+./
+├── typescript/
+│ ├── agentkit/
+│ ├── framework-extensions/
+│ | └── langchain/
+│ └── examples/
+│ ├── langchain-cdp-chatbot/
+│ ├── langchain-farcaster-chatbot/
+│ └── langchain-twitter-chatbot/
+├── python/
+│ ├── cdp-agentkit-core/
+│ ├── cdp-langchain/
+│ ├── twitter-langchain/
+│ └── examples/
+│ ├── cdp-langchain-chatbot/
+│ └── twitter-langchain-chatbot/
```
## Language-Specific Guides
@@ -85,4 +89,4 @@ Here are some common issues you might run into when developing in our monorepo a
| Issue | Resolution |
| ----- | ---------- |
-| Python imports are not resolving in VSCode / Cursor | Try opening the package folder in a new window. For example, `cd cdp-agentkit-core/python` and then `code .` or `cursor .` |
+| Python imports are not resolving in VSCode / Cursor | Try opening the package folder in a new window. For example, `cd python/cdp-agentkit-core` and then `code .` or `cursor .` |
diff --git a/README.md b/README.md
index 8879e0a91..471e8d9b5 100644
--- a/README.md
+++ b/README.md
@@ -17,9 +17,9 @@
[](https://pypistats.org/packages/cdp-agentkit-core)
-[](https://www.npmjs.com/package/@coinbase/cdp-agentkit-core)
-[](https://star-history.com/#coinbase/cdp-agentkit)
-[](https://github.com/coinbase/cdp-agentkit/issues)
+[](https://www.npmjs.com/package/@coinbase/agentkit)
+[](https://star-history.com/#coinbase/agentkit)
+[](https://github.com/coinbase/agentkit/issues)
@@ -49,11 +49,10 @@ AgentKit is [Coinbase Developer Platform's](https://docs.cdp.coinbase.com) frame
## 🚀 Quickstart
-### Python
+### Node.js
*Prerequisites*:
-- [Python 3.10+](https://www.python.org/downloads/)
-- [Poetry](https://python-poetry.org/docs/)
+- [Node.js 18+](https://nodejs.org/en/download/)
- [CDP Secret API Key](https://docs.cdp.coinbase.com/get-started/docs/cdp-api-keys#creating-secret-api-keys)
- [OpenAI API Key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-openai-api-key)
@@ -63,19 +62,19 @@ AgentKit is [Coinbase Developer Platform's](https://docs.cdp.coinbase.com) frame
# Clone the repository
git clone https://github.com/coinbase/agentkit.git
-# Navigate to the chatbot-python example
-cd agentkit/cdp-langchain/examples/chatbot-python
+# Navigate to the langchain-cdp-chatbot example
+cd agentkit/typescript/examples/langchain-cdp-chatbot
-# At this point, fill in your CDP API key name, private key, and OpenAI API key in the
-# .env.example file.
+# At this point, fill in your CDP API key name, private key, and OpenAI API key in
+# the .env.example file.
# Then, rename the .env.example file to .env
mv .env.example .env
# Install dependencies
-poetry install
+npm install
# Run the chatbot
-make run
+npm run start
```
2. Select "1. chat mode" and start telling your Agent to do things onchain!
@@ -92,10 +91,11 @@ Your wallet has been successfully funded with testnet ETH. You can view the tran
-------------------
```
-### Node.js
+### Python
*Prerequisites*:
-- [Node.js 18+](https://nodejs.org/en/download/)
+- [Python 3.10+](https://www.python.org/downloads/)
+- [Poetry](https://python-poetry.org/docs/)
- [CDP Secret API Key](https://docs.cdp.coinbase.com/get-started/docs/cdp-api-keys#creating-secret-api-keys)
- [OpenAI API Key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-openai-api-key)
@@ -105,19 +105,19 @@ Your wallet has been successfully funded with testnet ETH. You can view the tran
# Clone the repository
git clone https://github.com/coinbase/agentkit.git
-# Navigate to the chatbot-typescript example
-cd agentkit/cdp-langchain/examples/chatbot-typescript
+# Navigate to the chatbot-python example
+cd agentkit/python/cdp-langchain/examples/chatbot-python
-# At this point, fill in your CDP API key name, private key, and OpenAI API key in
-# the .env.example file.
+# At this point, fill in your CDP API key name, private key, and OpenAI API key in the
+# .env.example file.
# Then, rename the .env.example file to .env
mv .env.example .env
# Install dependencies
-npm install
+poetry install
# Run the chatbot
-npm run start
+make run
```
2. Select "1. chat mode" and start telling your Agent to do things onchain!
@@ -140,42 +140,23 @@ AgentKit is organized as a monorepo that contains multiple packages.
```
./
-├── cdp-agentkit-core/
-│ ├── python/
-│ └── typescript/
-├── cdp-langchain/
-│ ├── python/
-│ ├── typescript/
+├── typescript/
+│ ├── agentkit/
+│ ├── framework-extensions/
+│ | └── langchain/
│ └── examples/
-└── farcaster-langchain/
- ├── typescript/
- └── examples/
-└── twitter-langchain/
- ├── python/
- ├── typescript/
- └── examples/
+│ ├── langchain-cdp-chatbot/
+│ ├── langchain-farcaster-chatbot/
+│ └── langchain-twitter-chatbot/
+├── python/
+│ ├── cdp-agentkit-core/
+│ ├── cdp-langchain/
+│ ├── twitter-langchain/
+│ └── examples/
+│ ├── cdp-langchain-chatbot/
+│ └── twitter-langchain-chatbot/
```
-### cdp-agentkit-core
-
-Core primitives and framework-agnostic tools that are meant to be composable and used via AgentKit framework extensions (ie, `cdp-langchain`).
-See [CDP Agentkit Core](./cdp-agentkit-core/README.md) to get started!
-
-### cdp-langchain
-
-Langchain Toolkit extension of AgentKit. Enables agentic workflows to interact with onchain actions.
-See [CDP Langchain](./cdp-langchain/README.md) to get started!
-
-### farcaster-langchain
-
-Langchain Toolkit extension for Farcaster. Enables agentic workflows to interact with Farcaster, such as to post a tweet.
-See [Farcaster Langchain](./farcaster-langchain/typescript/README.md) to get started!
-
-### twitter-langchain
-
-Langchain Toolkit extension for Twitter. Enables agentic workflows to interact with Twitter, such as to post a tweet.
-See [Twitter Langchain](./twitter-langchain/README.md) to get started!
-
## 🤝 Contributing
**AgentKit is actively looking for community contributions!**
@@ -190,8 +171,8 @@ See [Twitter Langchain](./twitter-langchain/README.md) to get started!
- [AgentKit Core](https://coinbase.github.io/agentkit/cdp-agentkit-core/python/index.html)
- [AgentKit Langchain Extension](https://coinbase.github.io/agentkit/cdp-langchain/python/index.html)
- Node.js API References
- - [AgentKit Core](https://coinbase.github.io/agentkit/cdp-agentkit-core/typescript/index.html)
- - [AgentKit Langchain Extension](https://coinbase.github.io/agentkit/cdp-langchain/typescript/index.html)
+ - [AgentKit](https://coinbase.github.io/agentkit/agentkit/typescript/index.html)
+ - [AgentKit Langchain Extension](https://coinbase.github.io/agentkit-langchain/typescript/index.html)
## 🚨 Security and Bug Reports
@@ -225,4 +206,4 @@ The AgentKit software is novel and experimental, and is therefore provided on an
software may produce output that is inaccurate, incorrect, unpredictable or undesirable, and
it is the user's exclusive responsibility to evaluate the output and the use-case and
determine whether it is appropriate. The right to use the software is contingent on your
- agreement to the [CDP Terms of Service](https://www.coinbase.com/legal/developer-platform/terms-of-service) (except to the extent it conflicts with the Apache-2.0 license).
\ No newline at end of file
+ agreement to the [CDP Terms of Service](https://www.coinbase.com/legal/developer-platform/terms-of-service) (except to the extent it conflicts with the Apache-2.0 license).
diff --git a/cdp-agentkit-core/README.md b/cdp-agentkit-core/README.md
deleted file mode 100644
index 97bca4d9d..000000000
--- a/cdp-agentkit-core/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# Agentkit Core
-
-Framework agnostic primitives that are meant to be composable and used via Agentkit framework extensions.
-
-For Python, see [cdp-agentkit-core/python](./python/README.md).
-For TypeScript, see [cdp-agentkit-core/typescript](./typescript/README.md).
diff --git a/cdp-agentkit-core/python/docs/README.md b/cdp-agentkit-core/python/docs/README.md
deleted file mode 120000
index 32d46ee88..000000000
--- a/cdp-agentkit-core/python/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-../README.md
\ No newline at end of file
diff --git a/cdp-agentkit-core/typescript/jest.config.cjs b/cdp-agentkit-core/typescript/jest.config.cjs
deleted file mode 100644
index 57471c6d0..000000000
--- a/cdp-agentkit-core/typescript/jest.config.cjs
+++ /dev/null
@@ -1,20 +0,0 @@
-const baseConfig = require("../../jest.config.base.cjs");
-
-module.exports = {
- ...baseConfig,
- coveragePathIgnorePatterns: ["node_modules", "dist", "docs", "index.ts"],
- coverageThreshold: {
- "./src/actions/cdp/*": {
- branches: 50,
- functions: 50,
- statements: 50,
- lines: 50,
- },
- "./src/actions/cdp/defi/wow/actions/*": {
- branches: 50,
- functions: 50,
- statements: 50,
- lines: 50,
- },
- },
-};
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/address_reputation.ts b/cdp-agentkit-core/typescript/src/actions/cdp/address_reputation.ts
deleted file mode 100644
index 6d25e303a..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/address_reputation.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import { Wallet, Address } from "@coinbase/coinbase-sdk";
-import { z } from "zod";
-
-import { CdpAction } from "./cdp_action";
-
-const ADDRESS_REPUTATION_PROMPT = `
-This tool checks the reputation of an address on a given network. It takes:
-
-- network: The network to check the address on (e.g. "base-mainnet")
-- address: The Ethereum address to check
-
-Important notes:
-- This tool will not work on base-sepolia, you can default to using base-mainnet instead
-- The wallet's default address and its network may be used if not provided
-`;
-
-/**
- * Input schema for address reputation check.
- */
-export const AddressReputationInput = z
- .object({
- address: z
- .string()
- .regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address format")
- .describe("The Ethereum address to check"),
- network: z.string().describe("The network to check the address on"),
- })
- .strip()
- .describe("Input schema for address reputation check");
-
-/**
- * Check the reputation of an address.
- *
- * @param wallet - The wallet instance
- * @param args - The input arguments for the action
- * @returns A string containing reputation data or error message
- */
-export async function checkAddressReputation(
- args: z.infer,
-): Promise {
- try {
- const address = new Address(args.network, args.address);
- const reputation = await address.reputation();
- return reputation.toString();
- } catch (error) {
- return `Error checking address reputation: ${error}`;
- }
-}
-
-/**
- * Address reputation check action.
- */
-export class AddressReputationAction implements CdpAction {
- public name = "address_reputation";
- public description = ADDRESS_REPUTATION_PROMPT;
- public argsSchema = AddressReputationInput;
- public func = checkAddressReputation;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/cdp_action.ts b/cdp-agentkit-core/typescript/src/actions/cdp/cdp_action.ts
deleted file mode 100644
index 2166ef930..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/cdp_action.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { z } from "zod";
-import { Wallet } from "@coinbase/coinbase-sdk";
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export type CdpActionSchemaAny = z.ZodObject;
-
-/**
- * Represents the base structure for CDP Actions.
- */
-export interface CdpAction {
- /**
- * The name of the action
- */
- name: string;
-
- /**
- * A description of what the action does
- */
- description: string;
-
- /**
- * Schema for validating action arguments
- */
- argsSchema: TActionSchema;
-
- /**
- * The function to execute for this action
- */
- func:
- | ((wallet: Wallet, args: z.infer) => Promise)
- | ((args: z.infer) => Promise);
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/constants.ts b/cdp-agentkit-core/typescript/src/actions/cdp/constants.ts
deleted file mode 100644
index cd6c132cb..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/constants.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export const ERC20_APPROVE_ABI = [
- {
- constant: false,
- inputs: [
- { internalType: "address", name: "spender", type: "address" },
- { internalType: "uint256", name: "value", type: "uint256" },
- ],
- name: "approve",
- outputs: [{ internalType: "bool", name: "", type: "bool" }],
- payable: false,
- stateMutability: "nonpayable",
- type: "function",
- },
-];
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/data/pyth/fetch_price.ts b/cdp-agentkit-core/typescript/src/actions/cdp/data/pyth/fetch_price.ts
deleted file mode 100644
index d929e91e4..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/data/pyth/fetch_price.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { CdpAction } from "../../cdp_action";
-import { z } from "zod";
-
-const PYTH_FETCH_PRICE_PROMPT = `
-Fetch the price of a given price feed from Pyth.
-
-Inputs:
-- Pyth price feed ID
-
-Important notes:
-- Do not assume that a random ID is a Pyth price feed ID. If you are confused, ask a clarifying question.
-- This action only fetches price inputs from Pyth price feeds. No other source.
-- If you are asked to fetch the price from Pyth for a ticker symbol such as BTC, you must first use the pyth_fetch_price_feed_id
-action to retrieve the price feed ID before invoking the pyth_Fetch_price action
-`;
-
-/**
- * Input schema for Pyth fetch price action.
- */
-export const PythFetchPriceInput = z.object({
- priceFeedID: z.string().describe("The price feed ID to fetch the price for"),
-});
-
-/**
- * Fetches the price from Pyth given a Pyth price feed ID.
- *
- * @param args - The input arguments for the action.
- * @returns A message containing the price from the given price feed.
- */
-export async function pythFetchPrice(args: z.infer): Promise {
- const url = `https://hermes.pyth.network/v2/updates/price/latest?ids[]=${args.priceFeedID}`;
- const response = await fetch(url);
-
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
-
- const data = await response.json();
- const parsedData = data.parsed;
-
- if (parsedData.length === 0) {
- throw new Error(`No price data found for ${args.priceFeedID}`);
- }
-
- const priceInfo = parsedData[0].price;
- const price = BigInt(priceInfo.price);
- const exponent = priceInfo.expo;
-
- if (exponent < 0) {
- const adjustedPrice = price * BigInt(100);
- const divisor = BigInt(10) ** BigInt(-exponent);
- const scaledPrice = adjustedPrice / BigInt(divisor);
- const priceStr = scaledPrice.toString();
- const formattedPrice = `${priceStr.slice(0, -2)}.${priceStr.slice(-2)}`;
- return formattedPrice.startsWith(".") ? `0${formattedPrice}` : formattedPrice;
- }
-
- const scaledPrice = price / BigInt(10) ** BigInt(exponent);
- return scaledPrice.toString();
-}
-
-/**
- * Pyth fetch price action.
- */
-export class PythFetchPriceAction implements CdpAction {
- public name = "pyth_fetch_price";
- public description = PYTH_FETCH_PRICE_PROMPT;
- public argsSchema = PythFetchPriceInput;
- public func = pythFetchPrice;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/data/pyth/fetch_price_feed_id.ts b/cdp-agentkit-core/typescript/src/actions/cdp/data/pyth/fetch_price_feed_id.ts
deleted file mode 100644
index b627abcad..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/data/pyth/fetch_price_feed_id.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { CdpAction } from "../../cdp_action";
-import { z } from "zod";
-
-const PYTH_FETCH_PRICE_FEED_ID_PROMPT = `
-Fetch the price feed ID for a given token symbol from Pyth.
-`;
-
-/**
- * Input schema for Pyth fetch price feed ID action.
- */
-export const PythFetchPriceFeedIDInput = z.object({
- tokenSymbol: z.string().describe("The token symbol to fetch the price feed ID for"),
-});
-
-/**
- * Fetches the price feed ID from Pyth given a ticker symbol.
- *
- * @param args - The input arguments for the action.
- * @returns A message containing the price feed ID corresponding to the given ticker symbol.
- */
-export async function pythFetchPriceFeedID(
- args: z.infer,
-): Promise {
- const url = `https://hermes.pyth.network/v2/price_feeds?query=${args.tokenSymbol}&asset_type=crypto`;
- const response = await fetch(url);
-
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
-
- const data = await response.json();
-
- if (data.length === 0) {
- throw new Error(`No price feed found for ${args.tokenSymbol}`);
- }
-
- const filteredData = data.filter(
- (item: any) => item.attributes.base.toLowerCase() === args.tokenSymbol.toLowerCase(),
- );
-
- if (filteredData.length === 0) {
- throw new Error(`No price feed found for ${args.tokenSymbol}`);
- }
-
- return filteredData[0].id;
-}
-
-/**
- * Pyth fetch price feed ID action.
- */
-export class PythFetchPriceFeedIDAction implements CdpAction {
- public name = "pyth_fetch_price_feed_id";
- public description = PYTH_FETCH_PRICE_FEED_ID_PROMPT;
- public argsSchema = PythFetchPriceFeedIDInput;
- public func = pythFetchPriceFeedID;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/data/pyth/index.ts b/cdp-agentkit-core/typescript/src/actions/cdp/data/pyth/index.ts
deleted file mode 100644
index 1abca9c52..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/data/pyth/index.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { CdpAction, CdpActionSchemaAny } from "../../cdp_action";
-import { PythFetchPriceAction } from "./fetch_price";
-import { PythFetchPriceFeedIDAction } from "./fetch_price_feed_id";
-export * from "./fetch_price_feed_id";
-export * from "./fetch_price";
-
-/**
- * Retrieves all Pyth Network action instances.
- * WARNING: All new Pyth action classes must be instantiated here to be discovered.
- *
- * @returns Array of Pyth Network action instances
- */
-export function getAllPythActions(): CdpAction[] {
- // eslint-disable-next-line prettier/prettier
- return [new PythFetchPriceFeedIDAction(), new PythFetchPriceAction()];
-}
-
-export const PYTH_ACTIONS = getAllPythActions();
-
-// Export individual actions for direct imports
-// eslint-disable-next-line prettier/prettier
-export { PythFetchPriceFeedIDAction, PythFetchPriceAction };
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/defi/morpho/deposit.ts b/cdp-agentkit-core/typescript/src/actions/cdp/defi/morpho/deposit.ts
deleted file mode 100644
index 3c4973e98..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/defi/morpho/deposit.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-import { Asset, Wallet } from "@coinbase/coinbase-sdk";
-import { z } from "zod";
-import { Decimal } from "decimal.js";
-
-import { CdpAction } from "../../cdp_action";
-import { approve } from "../../utils";
-
-import { METAMORPHO_ABI } from "./constants";
-
-const DEPOSIT_PROMPT = `
-This tool allows depositing assets into a Morpho Vault.
-
-It takes:
-- vaultAddress: The address of the Morpho Vault to deposit to
-- assets: The amount of assets to deposit in whole units
- Examples for WETH:
- - 1 WETH
- - 0.1 WETH
- - 0.01 WETH
-- receiver: The address to receive the shares
-- tokenAddress: The address of the token to approve
-
-Important notes:
-- Make sure to use the exact amount provided. Do not convert units for assets for this action.
-- Please use a token address (example 0x4200000000000000000000000000000000000006) for the tokenAddress field. If you are unsure of the token address, please clarify what the requested token address is before continuing.
-`;
-
-/**
- * Input schema for Morpho Vault deposit action.
- */
-export const MorphoDepositInput = z
- .object({
- assets: z
- .string()
- .regex(/^\d+(\.\d+)?$/, "Must be a valid integer or decimal value")
- .describe("The quantity of assets to deposit, in whole units"),
- receiver: z
- .string()
- .regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address format")
- .describe(
- "The address that will own the position on the vault which will receive the shares",
- ),
- tokenAddress: z
- .string()
- .regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address format")
- .describe("The address of the assets token to approve for deposit"),
- vaultAddress: z
- .string()
- .regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address format")
- .describe("The address of the Morpho Vault to deposit to"),
- })
- .describe("Input schema for Morpho Vault deposit action");
-
-/**
- * Deposits assets into a Morpho Vault
- * @param Wallet - The wallet instance to execute the transaction
- * @param args - The input arguments for the action
- * @returns A success message with transaction details or an error message
- */
-export async function depositToMorpho(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- const assets = new Decimal(args.assets);
-
- if (assets.comparedTo(new Decimal(0.0)) != 1) {
- return "Error: Assets amount must be greater than 0";
- }
-
- try {
- const tokenAsset = await Asset.fetch(wallet.getNetworkId(), args.tokenAddress);
- const atomicAssets = tokenAsset.toAtomicAmount(assets);
-
- const approvalResult = await approve(
- wallet,
- args.tokenAddress,
- args.vaultAddress,
- atomicAssets,
- );
- if (approvalResult.startsWith("Error")) {
- return `Error approving Morpho Vault as spender: ${approvalResult}`;
- }
-
- const contractArgs = {
- assets: atomicAssets.toString(),
- receiver: args.receiver,
- };
-
- const invocation = await wallet.invokeContract({
- contractAddress: args.vaultAddress,
- method: "deposit",
- abi: METAMORPHO_ABI,
- args: contractArgs,
- });
-
- const result = await invocation.wait();
-
- return `Deposited ${args.assets} to Morpho Vault ${args.vaultAddress} with transaction hash: ${result.getTransactionHash()} and transaction link: ${result.getTransactionLink()}`;
- } catch (error) {
- return `Error depositing to Morpho Vault: ${error}`;
- }
-}
-
-/**
- * Morpho Vault deposit action.
- */
-export class MorphoDepositAction implements CdpAction {
- public name = "morpho_deposit";
- public description = DEPOSIT_PROMPT;
- public argsSchema = MorphoDepositInput;
- public func = depositToMorpho;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/defi/morpho/index.ts b/cdp-agentkit-core/typescript/src/actions/cdp/defi/morpho/index.ts
deleted file mode 100644
index 70204461d..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/defi/morpho/index.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { CdpAction, CdpActionSchemaAny } from "../../cdp_action";
-
-import { MorphoDepositAction } from "./deposit";
-import { MorphoWithdrawAction } from "./withdraw";
-
-/**
- * Retrieves all Morpho action instances.
- * WARNING: All new Morpho action classes must be instantiated here to be discovered.
- *
- * @returns - Array of Morpho action instances
- */
-export function getAllMorphoActions(): CdpAction[] {
- return [new MorphoDepositAction(), new MorphoWithdrawAction()];
-}
-
-export const MORPHO_ACTIONS = getAllMorphoActions();
-
-export { MorphoDepositAction, MorphoWithdrawAction };
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/defi/morpho/withdraw.ts b/cdp-agentkit-core/typescript/src/actions/cdp/defi/morpho/withdraw.ts
deleted file mode 100644
index 9c5b51e55..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/defi/morpho/withdraw.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import { Asset, Wallet } from "@coinbase/coinbase-sdk";
-import { z } from "zod";
-
-import { CdpAction } from "../../cdp_action";
-import { METAMORPHO_ABI } from "./constants";
-
-const WITHDRAW_PROMPT = `
-This tool allows withdrawing assets from a Morpho Vault. It takes:
-
-- vaultAddress: The address of the Morpho Vault to withdraw from
-- assets: The amount of assets to withdraw in atomic units
-- receiver: The address to receive the shares
-`;
-
-/**
- * Input schema for Morpho Vault withdraw action.
- */
-export const MorphoWithdrawInput = z
- .object({
- vaultAddress: z
- .string()
- .regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address format")
- .describe("The address of the Morpho Vault to withdraw from"),
- assets: z
- .string()
- .regex(/^\d+$/, "Must be a valid whole number")
- .describe("The amount of assets to withdraw in atomic units e.g. 1"),
- receiver: z
- .string()
- .regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address format")
- .describe("The address to receive the shares"),
- })
- .strip()
- .describe("Input schema for Morpho Vault withdraw action");
-
-/**
- * Withdraw assets from a Morpho Vault.
- *
- * @param wallet - The wallet to execute the withdrawal from
- * @param args - The input arguments for the action
- * @returns A success message with transaction details or error message
- */
-export async function withdrawFromMorpho(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- if (BigInt(args.assets) <= 0) {
- return "Error: Assets amount must be greater than 0";
- }
-
- try {
- const invocation = await wallet.invokeContract({
- contractAddress: args.vaultAddress,
- method: "withdraw",
- abi: METAMORPHO_ABI,
- args: {
- assets: args.assets,
- receiver: args.receiver,
- owner: args.receiver,
- },
- });
-
- const result = await invocation.wait();
-
- return `Withdrawn ${args.assets} from Morpho Vault ${args.vaultAddress} with transaction hash: ${result.getTransaction().getTransactionHash()} and transaction link: ${result.getTransaction().getTransactionLink()}`;
- } catch (error) {
- return `Error withdrawing from Morpho Vault: ${error}`;
- }
-}
-
-/**
- * Morpho Vault withdraw action.
- */
-export class MorphoWithdrawAction implements CdpAction {
- public name = "morpho_withdraw";
- public description = WITHDRAW_PROMPT;
- public argsSchema = MorphoWithdrawInput;
- public func = withdrawFromMorpho;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/actions/buy_token.ts b/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/actions/buy_token.ts
deleted file mode 100644
index 9ccd1a084..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/actions/buy_token.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import { CdpAction } from "../../../cdp_action";
-import { Wallet } from "@coinbase/coinbase-sdk";
-import { WOW_ABI } from "../constants";
-import { getHasGraduated } from "../uniswap/utils";
-import { getBuyQuote } from "../utils";
-import { z } from "zod";
-
-const WOW_BUY_TOKEN_PROMPT = `
-This tool can only be used to buy a Zora Wow ERC20 memecoin (also can be referred to as a bonding curve token) with ETH.
-Do not use this tool for any other purpose, or trading other assets.
-
-Inputs:
-- WOW token contract address
-- Address to receive the tokens
-- Amount of ETH to spend (in wei)
-
-Important notes:
-- The amount is a string and cannot have any decimal points, since the unit of measurement is wei.
-- 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
-- Minimum purchase amount is 100000000000000 wei (0.0000001 ETH)
-- Only supported on the following networks:
- - Base Sepolia (ie, 'base-sepolia')
- - Base Mainnet (ie, 'base', 'base-mainnet')
-`;
-
-/**
- * Input schema for buy token action.
- */
-export const WowBuyTokenInput = z
- .object({
- contractAddress: z.string().describe("The WOW token contract address"),
- amountEthInWei: z.string().describe("Amount of ETH to spend (in wei)"),
- })
- .strip()
- .describe("Instructions for buying WOW tokens");
-
-/**
- * Buys a Zora Wow ERC20 memecoin with ETH.
- *
- * @param wallet - The wallet to create the token from.
- * @param args - The input arguments for the action.
- * @returns A message containing the token purchase details.
- */
-export async function wowBuyToken(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- try {
- const tokenQuote = await getBuyQuote(
- wallet.getNetworkId(),
- args.contractAddress,
- args.amountEthInWei,
- );
-
- // Multiply by 99/100 and floor to get 99% of quote as minimum
- const minTokens = (BigInt(Math.floor(Number(tokenQuote) * 99)) / BigInt(100)).toString();
-
- const hasGraduated = await getHasGraduated(wallet.getNetworkId(), args.contractAddress);
-
- const invocation = await wallet.invokeContract({
- contractAddress: args.contractAddress,
- method: "buy",
- abi: WOW_ABI,
- args: {
- recipient: (await wallet.getDefaultAddress()).getId(),
- refundRecipient: (await wallet.getDefaultAddress()).getId(),
- orderReferrer: "0x0000000000000000000000000000000000000000",
- expectedMarketType: hasGraduated ? "1" : "0",
- minOrderSize: minTokens,
- sqrtPriceLimitX96: "0",
- comment: "",
- },
- amount: BigInt(args.amountEthInWei),
- assetId: "wei",
- });
-
- const result = await invocation.wait();
- return `Purchased WoW ERC20 memecoin with transaction hash: ${result
- .getTransaction()
- .getTransactionHash()}`;
- } catch (error) {
- return `Error buying Zora Wow ERC20 memecoin: ${error}`;
- }
-}
-
-/**
- * Zora Wow buy token action.
- */
-export class WowBuyTokenAction implements CdpAction {
- public name = "wow_buy_token";
- public description = WOW_BUY_TOKEN_PROMPT;
- public argsSchema = WowBuyTokenInput;
- public func = wowBuyToken;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/actions/create_token.ts b/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/actions/create_token.ts
deleted file mode 100644
index ff0c9f76c..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/actions/create_token.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import { CdpAction } from "../../../cdp_action";
-import { Wallet } from "@coinbase/coinbase-sdk";
-import { WOW_FACTORY_ABI, GENERIC_TOKEN_METADATA_URI, getFactoryAddress } from "../constants";
-import { z } from "zod";
-
-const WOW_CREATE_TOKEN_PROMPT = `
-This tool can only be used to create a Zora Wow ERC20 memecoin (also can be referred to as a bonding curve token) using the WoW factory.
-Do not use this tool for any other purpose, or for creating other types of tokens.
-
-Inputs:
-- Token name (e.g. WowCoin)
-- Token symbol (e.g. WOW)
-- Token URI (optional) - Contains metadata about the token
-
-Important notes:
-- Uses a bonding curve - no upfront liquidity needed
-- Only supported on the following networks:
- - Base Sepolia (ie, 'base-sepolia')
- - Base Mainnet (ie, 'base', 'base-mainnet')
-`;
-
-/**
- * Input schema for create token action.
- */
-export const WowCreateTokenInput = z
- .object({
- name: z.string().describe("The name of the token to create, e.g. WowCoin"),
- symbol: z.string().describe("The symbol of the token to create, e.g. WOW"),
- tokenUri: z
- .string()
- .optional()
- .describe(
- "The URI of the token metadata to store on IPFS, e.g. ipfs://QmY1GqprFYvojCcUEKgqHeDj9uhZD9jmYGrQTfA9vAE78J",
- ),
- })
- .strip()
- .describe("Instructions for creating a WOW token");
-
-/**
- * Creates a Zora Wow ERC20 memecoin.
- *
- * @param wallet - The wallet to create the token from.
- * @param args - The input arguments for the action.
- * @returns A message containing the token creation details.
- */
-export async function wowCreateToken(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- const factoryAddress = getFactoryAddress(wallet.getNetworkId());
-
- try {
- const invocation = await wallet.invokeContract({
- contractAddress: factoryAddress,
- method: "deploy",
- abi: WOW_FACTORY_ABI,
- args: {
- _tokenCreator: (await wallet.getDefaultAddress()).getId(),
- _platformReferrer: "0x0000000000000000000000000000000000000000",
- _tokenURI: args.tokenUri || GENERIC_TOKEN_METADATA_URI,
- _name: args.name,
- _symbol: args.symbol,
- },
- });
-
- const result = await invocation.wait();
- return `Created WoW ERC20 memecoin ${args.name} with symbol ${
- args.symbol
- } on network ${wallet.getNetworkId()}.\nTransaction hash for the token creation: ${result
- .getTransaction()
- .getTransactionHash()}`;
- } catch (error) {
- return `Error creating Zora Wow ERC20 memecoin: ${error}`;
- }
-}
-
-/**
- * Zora Wow create token action.
- */
-export class WowCreateTokenAction implements CdpAction {
- public name = "wow_create_token";
- public description = WOW_CREATE_TOKEN_PROMPT;
- public argsSchema = WowCreateTokenInput;
- public func = wowCreateToken;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/actions/sell_token.ts b/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/actions/sell_token.ts
deleted file mode 100644
index 4676de71c..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/actions/sell_token.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-import { CdpAction } from "../../../cdp_action";
-import { Wallet } from "@coinbase/coinbase-sdk";
-import { WOW_ABI } from "../constants";
-import { getHasGraduated } from "../uniswap/utils";
-import { getSellQuote } from "../utils";
-import { z } from "zod";
-
-const WOW_SELL_TOKEN_PROMPT = `
-This tool can only be used to sell a Zora Wow ERC20 memecoin (also can be referred to as a bonding curve token) for ETH.
-Do not use this tool for any other purpose, or trading other assets.
-
-Inputs:
-- WOW token contract address
-- Amount of tokens to sell (in wei)
-
-Important notes:
-- The amount is a string and cannot have any decimal points, since the unit of measurement is wei.
-- 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
-- Minimum purchase amount is 100000000000000 wei (0.0000001 ETH)
-- Only supported on the following networks:
- - Base Sepolia (ie, 'base-sepolia')
- - Base Mainnet (ie, 'base', 'base-mainnet')
-`;
-
-/**
- * Input schema for sell token action.
- */
-export const WowSellTokenInput = z
- .object({
- contractAddress: z
- .string()
- .describe(
- "The WOW token contract address, such as `0x036CbD53842c5426634e7929541eC2318f3dCF7e`",
- ),
- amountTokensInWei: z
- .string()
- .describe(
- "Amount of tokens to sell (in wei), meaning 1 is 1 wei or 0.000000000000000001 of the token",
- ),
- })
- .strip()
- .describe("Instructions for selling WOW tokens");
-
-/**
- * Sells WOW tokens for ETH.
- *
- * @param wallet - The wallet to sell the tokens from.
- * @param args - The input arguments for the action.
- * @returns A message confirming the sale with the transaction hash.
- */
-export async function wowSellToken(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- try {
- const ethQuote = await getSellQuote(
- wallet.getNetworkId(),
- args.contractAddress,
- args.amountTokensInWei,
- );
- const hasGraduated = await getHasGraduated(wallet.getNetworkId(), args.contractAddress);
-
- // Multiply by 98/100 and floor to get 98% of quote as minimum
- const minEth = (BigInt(Math.floor(Number(ethQuote) * 98)) / BigInt(100)).toString();
-
- const invocation = await wallet.invokeContract({
- contractAddress: args.contractAddress,
- method: "sell",
- abi: WOW_ABI,
- args: {
- tokensToSell: args.amountTokensInWei,
- recipient: (await wallet.getDefaultAddress()).getId(),
- orderReferrer: "0x0000000000000000000000000000000000000000",
- comment: "",
- expectedMarketType: hasGraduated ? "1" : "0",
- minPayoutSize: minEth,
- sqrtPriceLimitX96: "0",
- },
- });
-
- const result = await invocation.wait();
- return `Sold WoW ERC20 memecoin with transaction hash: ${result
- .getTransaction()
- .getTransactionHash()}`;
- } catch (error) {
- return `Error selling Zora Wow ERC20 memecoin: ${error}`;
- }
-}
-
-/**
- * Zora Wow sell token action.
- */
-export class WowSellTokenAction implements CdpAction {
- public name = "wow_sell_token";
- public description = WOW_SELL_TOKEN_PROMPT;
- public argsSchema = WowSellTokenInput;
- public func = wowSellToken;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/index.ts b/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/index.ts
deleted file mode 100644
index 9837e23f8..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/index.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { CdpAction, CdpActionSchemaAny } from "../../cdp_action";
-import { WowBuyTokenAction } from "./actions/buy_token";
-import { WowSellTokenAction } from "./actions/sell_token";
-import { WowCreateTokenAction } from "./actions/create_token";
-
-/**
- * Retrieves all WOW protocol action instances.
- * WARNING: All new WowAction classes must be instantiated here to be discovered.
- *
- * @returns Array of WOW protocol action instances
- */
-export function getAllWowActions(): CdpAction[] {
- // eslint-disable-next-line prettier/prettier
- return [new WowBuyTokenAction(), new WowSellTokenAction(), new WowCreateTokenAction()];
-}
-
-export const WOW_ACTIONS = getAllWowActions();
-
-// Export individual actions for direct imports
-// eslint-disable-next-line prettier/prettier
-export { WowBuyTokenAction, WowSellTokenAction, WowCreateTokenAction };
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/utils.ts b/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/utils.ts
deleted file mode 100644
index 7d0e66fdc..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/defi/wow/utils.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-import { readContract } from "@coinbase/coinbase-sdk";
-import { WOW_ABI } from "./constants";
-import { getHasGraduated, getUniswapQuote } from "./uniswap/utils";
-
-/**
- * Gets the current supply of a token.
- *
- * @param tokenAddress - Address of the token contract
- * @returns The current token supply
- */
-export async function getCurrentSupply(tokenAddress: string): Promise {
- const supply = await readContract({
- networkId: "base-sepolia",
- contractAddress: tokenAddress as `0x${string}`,
- method: "totalSupply",
- args: {},
- abi: WOW_ABI,
- });
-
- return supply as string;
-}
-
-/**
- * Gets quote for buying tokens.
- *
- * @param networkId - Network ID, either base-sepolia or base-mainnet
- * @param tokenAddress - Address of the token contract
- * @param amountEthInWei - Amount of ETH to buy (in wei)
- * @returns The buy quote amount
- */
-export async function getBuyQuote(
- networkId: string,
- tokenAddress: string,
- amountEthInWei: string,
-): Promise {
- const hasGraduated = await getHasGraduated(networkId, tokenAddress);
-
- const tokenQuote = (
- hasGraduated
- ? (await getUniswapQuote(networkId, tokenAddress, Number(amountEthInWei), "buy")).amountOut
- : await readContract({
- networkId: networkId,
- contractAddress: tokenAddress as `0x${string}`,
- method: "getEthBuyQuote",
- args: {
- ethOrderSize: amountEthInWei,
- },
- abi: WOW_ABI,
- })
- ) as string | number;
-
- return tokenQuote.toString();
-}
-
-/**
- * Gets quote for selling tokens.
- *
- * @param networkId - Network ID, either base-sepolia or base-mainnet
- * @param tokenAddress - Address of the token contract
- * @param amountTokensInWei - Amount of tokens to sell (in wei)
- * @returns The sell quote amount
- */
-export async function getSellQuote(
- networkId: string,
- tokenAddress: string,
- amountTokensInWei: string,
-): Promise {
- const hasGraduated = await getHasGraduated(networkId, tokenAddress);
-
- const tokenQuote = (
- hasGraduated
- ? (await getUniswapQuote(networkId, tokenAddress, Number(amountTokensInWei), "sell"))
- .amountOut
- : await readContract({
- networkId: networkId,
- contractAddress: tokenAddress as `0x${string}`,
- method: "getTokenSellQuote",
- args: {
- tokenOrderSize: amountTokensInWei,
- },
- abi: WOW_ABI,
- })
- ) as string | number;
-
- return tokenQuote.toString();
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/deploy_contract.ts b/cdp-agentkit-core/typescript/src/actions/cdp/deploy_contract.ts
deleted file mode 100644
index e3a09cfbe..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/deploy_contract.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-import { CdpAction } from "./cdp_action";
-import { Wallet } from "@coinbase/coinbase-sdk";
-import { z } from "zod";
-
-const DEPLOY_CONTRACT_PROMPT = `
-Deploys smart contract with required args: solidity version (string), solidity input json (string), contract name (string), and optional constructor args (Dict[str, Any])
-
-Input json structure:
-{"language":"Solidity","settings":{"remappings":[],"outputSelection":{"*":{"*":["abi","evm.bytecode"]}}},"sources":{}}
-
-You must set the outputSelection to {"*":{"*":["abi","evm.bytecode"]}} in the settings. The solidity version must be >= 0.8.0 and <= 0.8.28.
-
-Sources should contain one or more contracts with the following structure:
-{"contract_name.sol":{"content":"contract code"}}
-
-The contract code should be escaped. Contracts cannot import from external contracts but can import from one another.
-
-Constructor args are required if the contract has a constructor. They are a key-value
-map where the key is the arg name and the value is the arg value. Encode uint/int/bytes/string/address values as strings, boolean values as true/false. For arrays/tuples, encode based on contained type.
-`;
-
-const SolidityVersions = {
- "0.8.28": "0.8.28+commit.7893614a",
- "0.8.27": "0.8.27+commit.40a35a09",
- "0.8.26": "0.8.26+commit.8a97fa7a",
- "0.8.25": "0.8.25+commit.b61c2a91",
- "0.8.24": "0.8.24+commit.e11b9ed9",
- "0.8.23": "0.8.23+commit.f704f362",
- "0.8.22": "0.8.22+commit.4fc1097e",
- "0.8.21": "0.8.21+commit.d9974bed",
- "0.8.20": "0.8.20+commit.a1b79de6",
- "0.8.19": "0.8.19+commit.7dd6d404",
- "0.8.18": "0.8.18+commit.87f61d96",
- "0.8.17": "0.8.17+commit.8df45f5f",
- "0.8.16": "0.8.16+commit.07a7930e",
- "0.8.15": "0.8.15+commit.e14f2714",
- "0.8.14": "0.8.14+commit.80d49f37",
- "0.8.13": "0.8.13+commit.abaa5c0e",
- "0.8.12": "0.8.12+commit.f00d7308",
- "0.8.11": "0.8.11+commit.d7f03943",
- "0.8.10": "0.8.10+commit.fc410830",
- "0.8.9": "0.8.9+commit.e5eed63a",
- "0.8.8": "0.8.8+commit.dddeac2f",
- "0.8.7": "0.8.7+commit.e28d00a7",
- "0.8.6": "0.8.6+commit.11564f7e",
- "0.8.5": "0.8.5+commit.a4f2e591",
- "0.8.4": "0.8.4+commit.c7e474f2",
- "0.8.3": "0.8.3+commit.8d00100c",
- "0.8.2": "0.8.2+commit.661d1103",
- "0.8.1": "0.8.1+commit.df193b15",
- "0.8.0": "0.8.0+commit.c7dfd78e",
-} as const;
-
-/**
- * Input schema for deploy contract action.
- */
-export const DeployContractInput = z
- .object({
- solidityVersion: z
- .enum(Object.keys(SolidityVersions) as [string, ...string[]])
- .describe("The solidity compiler version"),
- solidityInputJson: z.string().describe("The input json for the solidity compiler"),
- contractName: z.string().describe("The name of the contract class to be deployed"),
- constructorArgs: z
- .record(z.string(), z.any())
- .describe("The constructor arguments for the contract")
- .optional(),
- })
- .strip()
- .describe("Instructions for deploying an arbitrary contract");
-
-/**
- * Deploys an arbitrary contract.
- *
- * @param wallet - The wallet to deploy the contract from.
- * @param args - The input arguments for the action. The three required fields are solidityVersion, solidityInputJson, and contractName. The constructorArgs field is only required if the contract has a constructor.
- * @returns A message containing the deployed contract address and details.
- */
-export async function deployContract(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- try {
- const solidityVersion = SolidityVersions[args.solidityVersion];
-
- const contract = await wallet.deployContract({
- solidityVersion: solidityVersion,
- solidityInputJson: args.solidityInputJson,
- contractName: args.contractName,
- constructorArgs: args.constructorArgs ?? {},
- });
-
- const result = await contract.wait();
-
- return `Deployed contract ${args.contractName} at address ${result.getContractAddress()}. Transaction link: ${result
- .getTransaction()!
- .getTransactionLink()}`;
- } catch (error) {
- return `Error deploying contract: ${error}`;
- }
-}
-
-/**
- * Deploy contract action.
- */
-export class DeployContractAction implements CdpAction {
- public name = "deploy_contract";
- public description = DEPLOY_CONTRACT_PROMPT;
- public argsSchema = DeployContractInput;
- public func = deployContract;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/deploy_nft.ts b/cdp-agentkit-core/typescript/src/actions/cdp/deploy_nft.ts
deleted file mode 100644
index a4ed60423..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/deploy_nft.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { CdpAction } from "./cdp_action";
-import { Wallet } from "@coinbase/coinbase-sdk";
-import { z } from "zod";
-
-const DEPLOY_NFT_PROMPT = `
-This tool will deploy an NFT (ERC-721) contract onchain from the wallet.
-It takes the name of the NFT collection, the symbol of the NFT collection, and the base URI for the token metadata as inputs.
-`;
-
-/**
- * Input schema for deploy NFT action.
- */
-export const DeployNftInput = z
- .object({
- name: z.string().describe("The name of the NFT collection"),
- symbol: z.string().describe("The symbol of the NFT collection"),
- baseURI: z.string().describe("The base URI for the token metadata"),
- })
- .strip()
- .describe("Instructions for deploying an NFT collection");
-
-/**
- * Deploys an NFT (ERC-721) token collection onchain from the wallet.
- *
- * @param wallet - The wallet to deploy the NFT from.
- * @param args - The input arguments for the action.
- * @returns A message containing the NFT token deployment details.
- */
-export async function deployNft(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- try {
- const nftContract = await wallet.deployNFT({
- name: args.name,
- symbol: args.symbol,
- baseURI: args.baseURI,
- });
-
- const result = await nftContract.wait();
-
- return `Deployed NFT Collection ${
- args.name
- } to address ${result.getContractAddress()} on network ${wallet.getNetworkId()}.\nTransaction hash for the deployment: ${result
- .getTransaction()!
- .getTransactionHash()}\nTransaction link for the deployment: ${result
- .getTransaction()!
- .getTransactionLink()}`;
- } catch (error) {
- return `Error deploying NFT: ${error}`;
- }
-}
-
-/**
- * Deploy NFT action.
- */
-export class DeployNftAction implements CdpAction {
- public name = "deploy_nft";
- public description = DEPLOY_NFT_PROMPT;
- public argsSchema = DeployNftInput;
- public func = deployNft;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/deploy_token.ts b/cdp-agentkit-core/typescript/src/actions/cdp/deploy_token.ts
deleted file mode 100644
index 6856870a3..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/deploy_token.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import { CdpAction } from "./cdp_action";
-import { Wallet, Amount } from "@coinbase/coinbase-sdk";
-import { z } from "zod";
-
-const DEPLOY_TOKEN_PROMPT = `
-This tool will deploy an ERC20 token smart contract. It takes the token name, symbol, and total supply as input.
-The token will be deployed using the wallet's default address as the owner and initial token holder.
-`;
-
-/**
- * Input schema for deploy token action.
- */
-export const DeployTokenInput = z
- .object({
- name: z.string().describe("The name of the token"),
- symbol: z.string().describe("The token symbol"),
- totalSupply: z.custom().describe("The total supply of tokens to mint"),
- })
- .strip()
- .describe("Instructions for deploying a token");
-
-/**
- * Deploys an ERC20 token smart contract.
- *
- * @param wallet - The wallet to deploy the Token from.
- * @param args - The input arguments for the action.
- * @returns A message containing the deployed token contract address and details.
- */
-export async function deployToken(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- try {
- const tokenContract = await wallet.deployToken({
- name: args.name,
- symbol: args.symbol,
- totalSupply: args.totalSupply,
- });
-
- const result = await tokenContract.wait();
-
- return `Deployed ERC20 token contract ${args.name} (${args.symbol}) with total supply of ${
- args.totalSupply
- } tokens at address ${result.getContractAddress()}. Transaction link: ${result
- .getTransaction()!
- .getTransactionLink()}`;
- } catch (error) {
- return `Error deploying token: ${error}`;
- }
-}
-
-/**
- * Deploy token action.
- */
-export class DeployTokenAction implements CdpAction {
- public name = "deploy_token";
- public description = DEPLOY_TOKEN_PROMPT;
- public argsSchema = DeployTokenInput;
- public func = deployToken;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/get_balance.ts b/cdp-agentkit-core/typescript/src/actions/cdp/get_balance.ts
deleted file mode 100644
index 9463bb073..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/get_balance.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { CdpAction } from "./cdp_action";
-import { Wallet } from "@coinbase/coinbase-sdk";
-import Decimal from "decimal.js";
-import { z } from "zod";
-
-const GET_BALANCE_PROMPT = `
-This tool will get the balance of all the addresses in the wallet for a given asset.
-It takes the asset ID as input. Always use 'eth' for the native asset ETH and 'usdc' for USDC.
-`;
-
-/**
- * Input schema for get balance action.
- */
-export const GetBalanceInput = z
- .object({
- assetId: z.string().describe("The asset ID to get the balance for"),
- })
- .strip()
- .describe("Instructions for getting wallet balance");
-
-/**
- * Gets balance for all addresses in the wallet for a given asset.
- *
- * @param wallet - The wallet to get the balance for.
- * @param args - The input arguments for the action.
- * @returns A message containing the balance information.
- */
-export async function getBalance(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- const balances: Record = {};
-
- try {
- const addresses = await wallet.listAddresses();
- for (const address of addresses) {
- const balance = await address.getBalance(args.assetId);
- balances[address.getId()] = balance;
- }
-
- const balanceLines = Object.entries(balances).map(([addr, balance]) => `${addr}: ${balance}`);
- const formattedBalances = balanceLines.join("\n");
- return `Balances for wallet ${wallet.getId()}:\n${formattedBalances}`;
- } catch (error) {
- return `Error getting balance for all addresses in the wallet: ${error}`;
- }
-}
-
-/**
- * Get wallet balance action.
- */
-export class GetBalanceAction implements CdpAction {
- public name = "get_balance";
- public description = GET_BALANCE_PROMPT;
- public argsSchema = GetBalanceInput;
- public func = getBalance;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/get_balance_nft.ts b/cdp-agentkit-core/typescript/src/actions/cdp/get_balance_nft.ts
deleted file mode 100644
index 3c81743af..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/get_balance_nft.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { CdpAction } from "./cdp_action";
-import { readContract, Wallet } from "@coinbase/coinbase-sdk";
-import { Hex } from "viem";
-import { z } from "zod";
-
-const GET_BALANCE_NFT_PROMPT = `
-This tool will get the NFTs (ERC721 tokens) owned by the wallet for a specific NFT contract.
-
-It takes the following inputs:
-- contractAddress: The NFT contract address to check
-- address: (Optional) The address to check NFT balance for. If not provided, uses the wallet's default address
-`;
-
-/**
- * Input schema for get NFT balance action.
- */
-export const GetBalanceNftInput = z
- .object({
- contractAddress: z.string().describe("The NFT contract address to check balance for"),
- address: z
- .string()
- .optional()
- .describe(
- "The address to check NFT balance for. If not provided, uses the wallet's default address",
- ),
- })
- .strip()
- .describe("Instructions for getting NFT balance");
-
-/**
- * Gets NFT balance for a specific contract.
- *
- * @param wallet - The wallet to check balance from.
- * @param args - The input arguments for the action.
- * @returns A message containing the NFT balance details.
- */
-export async function getBalanceNft(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- try {
- const checkAddress = args.address || (await wallet.getDefaultAddress()).getId();
-
- const ownedTokens = await readContract({
- contractAddress: args.contractAddress as Hex,
- networkId: wallet.getNetworkId(),
- method: "tokensOfOwner",
- args: { owner: checkAddress },
- });
-
- if (!ownedTokens || ownedTokens.length === 0) {
- return `Address ${checkAddress} owns no NFTs in contract ${args.contractAddress}`;
- }
-
- const tokenList = ownedTokens.map(String).join(", ");
- return `Address ${checkAddress} owns ${ownedTokens.length} NFTs in contract ${args.contractAddress}.\nToken IDs: ${tokenList}`;
- } catch (error) {
- return `Error getting NFT balance for address ${args.address} in contract ${args.contractAddress}: ${error}`;
- }
-}
-
-/**
- * Get NFT balance action.
- */
-export class GetBalanceNftAction implements CdpAction {
- name = "get_balance_nft";
- description = GET_BALANCE_NFT_PROMPT;
- argsSchema = GetBalanceNftInput;
- func = getBalanceNft;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/get_wallet_details.ts b/cdp-agentkit-core/typescript/src/actions/cdp/get_wallet_details.ts
deleted file mode 100644
index 94b14fdc0..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/get_wallet_details.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import { z } from "zod";
-import { CdpAction } from "./cdp_action";
-import { Wallet } from "@coinbase/coinbase-sdk";
-
-/**
- * Input schema for get wallet details action.
- * This schema intentionally accepts no parameters as the wallet is injected separately.
- */
-export const GetWalletDetailsInput = z.object({});
-
-/**
- * Gets a wallet's details.
- *
- * @param wallet - The wallet to get details from.
- * @param _ - The input arguments for the action.
- * @returns A message containing the wallet details.
- */
-export async function getWalletDetails(
- wallet: Wallet,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- _: z.infer,
-): Promise {
- try {
- const defaultAddress = await wallet.getDefaultAddress();
- return `Wallet: ${wallet.getId()} on network: ${wallet.getNetworkId()} with default address: ${defaultAddress.getId()}`;
- } catch (error) {
- return `Error getting wallet details: ${error}`;
- }
-}
-
-/**
- * Get wallet details action.
- */
-export class GetWalletDetailsAction implements CdpAction {
- /**
- * The name of the action
- */
- public name = "get_wallet_details";
-
- /**
- * A description of what the action does
- */
- public description = "This tool will get details about the MPC Wallet.";
-
- /**
- * Schema for validating action arguments
- */
- public argsSchema = GetWalletDetailsInput;
-
- /**
- * The function to execute for this action
- */
- public func = getWalletDetails;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/index.ts b/cdp-agentkit-core/typescript/src/actions/cdp/index.ts
deleted file mode 100644
index 368928b04..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/index.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import { CdpAction, CdpActionSchemaAny } from "./cdp_action";
-import { AddressReputationAction } from "./address_reputation";
-import { DeployNftAction } from "./deploy_nft";
-import { DeployTokenAction } from "./deploy_token";
-import { DeployContractAction } from "./deploy_contract";
-import { GetBalanceAction } from "./get_balance";
-import { GetBalanceNftAction } from "./get_balance_nft";
-import { GetWalletDetailsAction } from "./get_wallet_details";
-import { MintNftAction } from "./mint_nft";
-import { RegisterBasenameAction } from "./register_basename";
-import { RequestFaucetFundsAction } from "./request_faucet_funds";
-import { TradeAction } from "./trade";
-import { TransferAction } from "./transfer";
-import { TransferNftAction } from "./transfer_nft";
-import { WrapEthAction } from "./wrap_eth";
-
-import { MORPHO_ACTIONS } from "./defi/morpho";
-import { PYTH_ACTIONS } from "./data/pyth";
-import { WOW_ACTIONS } from "./defi/wow";
-
-/**
- * Retrieves all CDP action instances.
- * WARNING: All new CdpAction classes must be instantiated here to be discovered.
- *
- * @returns - Array of CDP action instances
- */
-export function getAllCdpActions(): CdpAction[] {
- return [
- new AddressReputationAction(),
- new GetWalletDetailsAction(),
- new DeployNftAction(),
- new DeployTokenAction(),
- new DeployContractAction(),
- new GetBalanceAction(),
- new GetBalanceNftAction(),
- new MintNftAction(),
- new RegisterBasenameAction(),
- new RequestFaucetFundsAction(),
- new TradeAction(),
- new TransferAction(),
- new TransferNftAction(),
- new WrapEthAction(),
- ];
-}
-
-export const CDP_ACTIONS = getAllCdpActions()
- .concat(MORPHO_ACTIONS)
- .concat(PYTH_ACTIONS)
- .concat(WOW_ACTIONS);
-
-export {
- CdpAction,
- CdpActionSchemaAny,
- AddressReputationAction,
- GetWalletDetailsAction,
- DeployNftAction,
- DeployTokenAction,
- DeployContractAction,
- GetBalanceAction,
- GetBalanceNftAction,
- MintNftAction,
- RegisterBasenameAction,
- RequestFaucetFundsAction,
- TradeAction,
- TransferAction,
- TransferNftAction,
- WrapEthAction,
-};
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/mint_nft.ts b/cdp-agentkit-core/typescript/src/actions/cdp/mint_nft.ts
deleted file mode 100644
index a3268d58c..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/mint_nft.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import { CdpAction } from "./cdp_action";
-import { Wallet } from "@coinbase/coinbase-sdk";
-import { z } from "zod";
-
-const MINT_NFT_PROMPT = `
-This tool will mint an NFT (ERC-721) to a specified destination address onchain via a contract invocation.
-It takes the contract address of the NFT onchain and the destination address onchain that will receive the NFT as inputs.
-Do not use the contract address as the destination address. If you are unsure of the destination address, please ask the user before proceeding.
-`;
-
-/**
- * Input schema for mint NFT action.
- */
-export const MintNftInput = z
- .object({
- contractAddress: z.string().describe("The contract address of the NFT to mint"),
- destination: z.string().describe("The destination address that will receive the NFT"),
- })
- .strip()
- .describe("Instructions for minting an NFT");
-
-/**
- * Mints an NFT (ERC-721) to a specified destination address onchain.
- *
- * @param wallet - The wallet to mint the NFT from.
- * @param args - The input arguments for the action.
- * @returns A message containing the NFT mint details.
- */
-export async function mintNft(wallet: Wallet, args: z.infer): Promise {
- const mintArgs = {
- to: args.destination,
- quantity: "1",
- };
-
- try {
- const mintInvocation = await wallet.invokeContract({
- contractAddress: args.contractAddress,
- method: "mint",
- args: mintArgs,
- });
-
- const result = await mintInvocation.wait();
-
- return `Minted NFT from contract ${args.contractAddress} to address ${
- args.destination
- } on network ${wallet.getNetworkId()}.\nTransaction hash for the mint: ${result
- .getTransaction()
- .getTransactionHash()}\nTransaction link for the mint: ${result
- .getTransaction()
- .getTransactionLink()}`;
- } catch (error) {
- return `Error minting NFT: ${error}`;
- }
-}
-
-/**
- * Mint NFT action.
- */
-export class MintNftAction implements CdpAction {
- public name = "mint_nft";
- public description = MINT_NFT_PROMPT;
- public argsSchema = MintNftInput;
- public func = mintNft;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/register_basename.ts b/cdp-agentkit-core/typescript/src/actions/cdp/register_basename.ts
deleted file mode 100644
index 46fff2fa8..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/register_basename.ts
+++ /dev/null
@@ -1,202 +0,0 @@
-import { CdpAction } from "./cdp_action";
-import { Coinbase, Wallet } from "@coinbase/coinbase-sdk";
-import { encodeFunctionData, namehash } from "viem";
-import { z } from "zod";
-import { Decimal } from "decimal.js";
-
-const REGISTER_BASENAME_PROMPT = `
-This tool will register a Basename for the agent. The agent should have a wallet associated to register a Basename.
-When your network ID is 'base-mainnet' (also sometimes known simply as 'base'), the name must end with .base.eth, and when your network ID is 'base-sepolia', it must ends with .basetest.eth.
-Do not suggest any alternatives and never try to register a Basename with another postfix. The prefix of the name must be unique so if the registration of the
-Basename fails, you should prompt to try again with a more unique name.
-`;
-
-// Contract addresses
-export const BASENAMES_REGISTRAR_CONTROLLER_ADDRESS_MAINNET =
- "0x4cCb0BB02FCABA27e82a56646E81d8c5bC4119a5";
-export const BASENAMES_REGISTRAR_CONTROLLER_ADDRESS_TESTNET =
- "0x49aE3cC2e3AA768B1e5654f5D3C6002144A59581";
-
-export const L2_RESOLVER_ADDRESS_MAINNET = "0xC6d566A56A1aFf6508b41f6c90ff131615583BCD";
-export const L2_RESOLVER_ADDRESS_TESTNET = "0x6533C94869D28fAA8dF77cc63f9e2b2D6Cf77eBA";
-
-// Default registration duration (1 year in seconds)
-export const REGISTRATION_DURATION = "31557600";
-
-// Relevant ABI for L2 Resolver Contract.
-export const L2_RESOLVER_ABI = [
- {
- inputs: [
- { internalType: "bytes32", name: "node", type: "bytes32" },
- { internalType: "address", name: "a", type: "address" },
- ],
- name: "setAddr",
- outputs: [],
- stateMutability: "nonpayable",
- type: "function",
- },
- {
- inputs: [
- { internalType: "bytes32", name: "node", type: "bytes32" },
- { internalType: "string", name: "newName", type: "string" },
- ],
- name: "setName",
- outputs: [],
- stateMutability: "nonpayable",
- type: "function",
- },
-];
-
-// Relevant ABI for Basenames Registrar Controller Contract.
-export const REGISTRAR_ABI = [
- {
- inputs: [
- {
- components: [
- {
- internalType: "string",
- name: "name",
- type: "string",
- },
- {
- internalType: "address",
- name: "owner",
- type: "address",
- },
- {
- internalType: "uint256",
- name: "duration",
- type: "uint256",
- },
- {
- internalType: "address",
- name: "resolver",
- type: "address",
- },
- {
- internalType: "bytes[]",
- name: "data",
- type: "bytes[]",
- },
- {
- internalType: "bool",
- name: "reverseRecord",
- type: "bool",
- },
- ],
- internalType: "struct RegistrarController.RegisterRequest",
- name: "request",
- type: "tuple",
- },
- ],
- name: "register",
- outputs: [],
- stateMutability: "payable",
- type: "function",
- },
-];
-
-/**
- * Input schema for registering a Basename.
- */
-export const RegisterBasenameInput = z
- .object({
- basename: z.string().describe("The Basename to assign to the agent"),
- amount: z.string().default("0.002").describe("The amount of ETH to pay for registration"),
- })
- .strip()
- .describe("Instructions for registering a Basename");
-
-/**
- * Creates registration arguments for Basenames.
- *
- * @param baseName - The Basename (e.g., "example.base.eth" or "example.basetest.eth").
- * @param addressId - The Ethereum address.
- * @param isMainnet - True if on mainnet, False if on testnet.
- * @returns Formatted arguments for the register contract method.
- */
-function createRegisterContractMethodArgs(
- baseName: string,
- addressId: string,
- isMainnet: boolean,
-): object {
- const l2ResolverAddress = isMainnet ? L2_RESOLVER_ADDRESS_MAINNET : L2_RESOLVER_ADDRESS_TESTNET;
- const suffix = isMainnet ? ".base.eth" : ".basetest.eth";
-
- const addressData = encodeFunctionData({
- abi: L2_RESOLVER_ABI,
- functionName: "setAddr",
- args: [namehash(baseName), addressId],
- });
- const nameData = encodeFunctionData({
- abi: L2_RESOLVER_ABI,
- functionName: "setName",
- args: [namehash(baseName), baseName],
- });
-
- const registerArgs = {
- request: [
- baseName.replace(suffix, ""),
- addressId,
- REGISTRATION_DURATION,
- l2ResolverAddress,
- [addressData, nameData],
- true,
- ],
- };
-
- return registerArgs;
-}
-
-/**
- * Registers a Basename for the agent.
- *
- * @param wallet - The wallet to register the Basename with.
- * @param args - The input arguments for the action.
- * @returns Confirmation message with the basename.
- */
-export async function registerBasename(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- const addressId = (await wallet.getDefaultAddress()).getId();
- const isMainnet = wallet.getNetworkId() === Coinbase.networks.BaseMainnet;
-
- const suffix = isMainnet ? ".base.eth" : ".basetest.eth";
- if (!args.basename.endsWith(suffix)) {
- args.basename += suffix;
- }
-
- const registerArgs = createRegisterContractMethodArgs(args.basename, addressId, isMainnet);
-
- try {
- const contractAddress = isMainnet
- ? BASENAMES_REGISTRAR_CONTROLLER_ADDRESS_MAINNET
- : BASENAMES_REGISTRAR_CONTROLLER_ADDRESS_TESTNET;
-
- const invocation = await wallet.invokeContract({
- contractAddress,
- method: "register",
- args: registerArgs,
- abi: REGISTRAR_ABI,
- amount: new Decimal(args.amount),
- assetId: "eth",
- });
-
- await invocation.wait();
- return `Successfully registered basename ${args.basename} for address ${addressId}`;
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- } catch (error) {
- return `Error registering basename: Error: ${error}`;
- }
-}
-
-/**
- * Register Basename action.
- */
-export class RegisterBasenameAction implements CdpAction {
- public name = "register_basename";
- public description = REGISTER_BASENAME_PROMPT;
- public argsSchema = RegisterBasenameInput;
- public func = registerBasename;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/request_faucet_funds.ts b/cdp-agentkit-core/typescript/src/actions/cdp/request_faucet_funds.ts
deleted file mode 100644
index d56eb694b..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/request_faucet_funds.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { CdpAction } from "./cdp_action";
-import { Wallet } from "@coinbase/coinbase-sdk";
-import { z } from "zod";
-
-const REQUEST_FAUCET_FUNDS_PROMPT = `
-This tool will request test tokens from the faucet for the default address in the wallet. It takes the wallet and asset ID as input.
-If no asset ID is provided the faucet defaults to ETH. Faucet is only allowed on 'base-sepolia' and can only provide asset ID 'eth' or 'usdc'.
-You are not allowed to faucet with any other network or asset ID. If you are on another network, suggest that the user sends you some ETH
-from another wallet and provide the user with your wallet details.
-`;
-
-/**
- * Input schema for request faucet funds action.
- */
-export const RequestFaucetFundsInput = z
- .object({
- assetId: z.string().optional().describe("The optional asset ID to request from faucet"),
- })
- .strip()
- .describe("Instructions for requesting faucet funds");
-
-/**
- * Requests test tokens from the faucet for the default address in the wallet.
- *
- * @param wallet - The wallet to receive tokens.
- * @param args - The input arguments for the action.
- * @returns A confirmation message with transaction details.
- */
-export async function requestFaucetFunds(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- try {
- // Request funds from the faucet
- const faucetTx = await wallet.faucet(args.assetId || undefined);
-
- // Wait for the faucet transaction to be confirmed
- const result = await faucetTx.wait();
-
- return `Received ${
- args.assetId || "ETH"
- } from the faucet. Transaction: ${result.getTransactionLink()}`;
- } catch (error) {
- return `Error requesting faucet funds: ${error}`;
- }
-}
-
-/**
- * Request faucet funds action.
- */
-export class RequestFaucetFundsAction implements CdpAction {
- public name = "request_faucet_funds";
- public description = REQUEST_FAUCET_FUNDS_PROMPT;
- public argsSchema = RequestFaucetFundsInput;
- public func = requestFaucetFunds;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/social/farcaster/account_details.ts b/cdp-agentkit-core/typescript/src/actions/cdp/social/farcaster/account_details.ts
deleted file mode 100644
index e81e82084..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/social/farcaster/account_details.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * This module provides functionality to retrieve Farcaster account details.
- */
-
-import { z } from "zod";
-import { FarcasterAction } from "./farcaster_action";
-
-/**
- * Prompt message describing the account details tool.
- * A successful response will return a message with the API response in JSON format,
- * while a failure response will indicate an error from the Farcaster API.
- */
-const ACCOUNT_DETAILS_PROMPT = `
-This tool will retrieve the account details for the agent's Farcaster account.
-The tool takes the FID of the agent's account.
-
-A successful response will return a message with the API response as a JSON payload:
- { "object": "user", "fid": 193," username": "derek", "display_name": "Derek", ... }
-
-A failure response will return a message with the Farcaster API request error:
- Unable to retrieve account details.
-`;
-
-/**
- * Input argument schema for the account_details action.
- */
-export const AccountDetailsInput = z
- .object({})
- .strip()
- .describe("Input schema for retrieving account details");
-
-/**
- * Retrieves agent's Farcaster account details.
- *
- * @param _ The input arguments for the action.
- * @returns A message containing account details for the agent's Farcaster account.
- */
-export async function accountDetails(_: z.infer): Promise {
- try {
- const AGENT_FID = process.env.AGENT_FID;
- const NEYNAR_API_KEY = process.env.NEYNAR_API_KEY;
-
- const headers: HeadersInit = {
- accept: "application/json",
- "x-api-key": NEYNAR_API_KEY!,
- "x-neynar-experimental": "true",
- };
-
- const response = await fetch(
- `https://api.neynar.com/v2/farcaster/user/bulk?fids=${AGENT_FID}`,
- {
- method: "GET",
- headers,
- },
- );
- const { users } = await response.json();
- return `Successfully retrieved Farcaster account details:\n${JSON.stringify(users[0])}`;
- } catch (error) {
- return `Error retrieving Farcaster account details:\n${error}`;
- }
-}
-
-/**
- * Account Details Action
- */
-export class FarcasterAccountDetailsAction implements FarcasterAction {
- public name = "farcaster_account_details";
- public description = ACCOUNT_DETAILS_PROMPT;
- public argsSchema = AccountDetailsInput;
- public func = accountDetails;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/social/farcaster/farcaster_action.ts b/cdp-agentkit-core/typescript/src/actions/cdp/social/farcaster/farcaster_action.ts
deleted file mode 100644
index b776073c3..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/social/farcaster/farcaster_action.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { z } from "zod";
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export type FarcasterActionSchemaAny = z.ZodObject;
-
-/**
- * Represents the base structure for Farcaster Actions.
- */
-export interface FarcasterAction {
- /**
- * The name of the action.
- */
- name: string;
-
- /**
- * A description of what the action does
- */
- description: string;
-
- /**
- * Schema for validating action arguments
- */
- argsSchema: TActionSchema;
-
- /**
- * The function to execute for this action
- */
- func: (args: z.infer) => Promise;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/social/farcaster/index.ts b/cdp-agentkit-core/typescript/src/actions/cdp/social/farcaster/index.ts
deleted file mode 100644
index e4f62dc44..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/social/farcaster/index.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * This module exports various Farcaster action instances and their associated types.
- */
-
-import { FarcasterAction, FarcasterActionSchemaAny } from "./farcaster_action";
-import { FarcasterAccountDetailsAction } from "./account_details";
-import { FarcasterPostCastAction } from "./post_cast";
-
-/**
- * Retrieve an array of Farcaster action instances.
- *
- * @returns {FarcasterAction[]} An array of Farcaster action instances.
- */
-export function getAllFarcasterActions(): FarcasterAction[] {
- return [new FarcasterAccountDetailsAction(), new FarcasterPostCastAction()];
-}
-
-/**
- * All available Farcaster actions.
- */
-export const FARCASTER_ACTIONS = getAllFarcasterActions();
-
-/**
- * All Farcaster action types.
- */
-export {
- FarcasterAction,
- FarcasterActionSchemaAny,
- FarcasterAccountDetailsAction,
- FarcasterPostCastAction,
-};
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/social/farcaster/post_cast.ts b/cdp-agentkit-core/typescript/src/actions/cdp/social/farcaster/post_cast.ts
deleted file mode 100644
index fa3b97a7d..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/social/farcaster/post_cast.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * This module provides functionality to post a cast on Farcaster.
- */
-
-import { z } from "zod";
-import { FarcasterAction } from "./farcaster_action";
-
-/**
- * Prompt message describing the post cast tool.
- * A successful response will return a message with the API response in JSON format,
- * while a failure response will indicate an error from the Farcaster API.
- */
-const POST_CAST_PROMPT = `
-This tool will post a cast to Farcaster. The tool takes the text of the cast as input. Casts can be maximum 280 characters.
-
-A successful response will return a message with the API response as a JSON payload:
- {}
-
-A failure response will return a message with the Farcaster API request error:
- You are not allowed to post a cast with duplicate content.
-`;
-
-/**
- * Input argument schema for the post cast action.
- */
-export const PostCastInput = z
- .object({
- castText: z.string().max(280, "Cast text must be a maximum of 280 characters."),
- })
- .strip()
- .describe("Input schema for posting a text-based cast");
-
-/**
- * Posts a cast on Farcaster.
- *
- * @param args - The input arguments for the action.
- * @returns A message indicating the success or failure of the cast posting.
- */
-export async function postCast(args: z.infer): Promise {
- try {
- const NEYNAR_API_KEY = process.env.NEYNAR_API_KEY;
- const SIGNER_UUID = process.env.NEYNAR_MANAGED_SIGNER;
-
- const headers: HeadersInit = {
- api_key: NEYNAR_API_KEY!,
- "Content-Type": "application/json",
- };
-
- const response = await fetch("https://api.neynar.com/v2/farcaster/cast", {
- method: "POST",
- headers,
- body: JSON.stringify({
- signer_uuid: SIGNER_UUID,
- text: args.castText,
- }),
- });
- const data = await response.json();
- return `Successfully posted cast to Farcaster:\n${JSON.stringify(data)}`;
- } catch (error) {
- return `Error posting to Farcaster:\n${error}`;
- }
-}
-
-/**
- * Post Cast Action
- */
-export class FarcasterPostCastAction implements FarcasterAction {
- public name = "farcaster_post_cast";
- public description = POST_CAST_PROMPT;
- public argsSchema = PostCastInput;
- public func = postCast;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/account_details.ts b/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/account_details.ts
deleted file mode 100644
index 6a2ce67ef..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/account_details.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * This module provides functionality to retrieve account details for the currently authenticated Twitter (X) user.
- */
-
-import { z } from "zod";
-import { TwitterAction } from "./twitter_action";
-import { TwitterApi } from "twitter-api-v2";
-
-/**
- * Prompt message describing the account details tool.
- * A successful response will return account details in JSON format,
- * while a failure response will indicate an error from the Twitter API.
- */
-const ACCOUNT_DETAILS_PROMPT = `
-This tool will return account details for the currently authenticated Twitter (X) user context.
-
-A successful response will return a message with the api response as a json payload:
- {"data": {"id": "1853889445319331840", "name": "CDP AgentKit", "username": "CDPAgentKit"}}
-
-A failure response will return a message with a Twitter API request error:
- Error retrieving authenticated user account: 429 Too Many Requests
-`;
-
-/**
- * Input argument schema for the account details action.
- */
-export const AccountDetailsInput = z
- .object({})
- .strip()
- .describe("Input schema for retrieving account details");
-
-/**
- * Get the authenticated Twitter (X) user account details.
- *
- * @param client - The Twitter (X) client used to authenticate with.
- * @param _ - The input arguments for the action.
- * @returns A message containing account details for the authenticated user context.
- */
-export async function accountDetails(
- client: TwitterApi,
- _: z.infer,
-): Promise {
- try {
- const response = await client.v2.me();
- response.data.url = `https://x.com/${response.data.username}`;
- return `Successfully retrieved authenticated user account details:\n${JSON.stringify(
- response,
- )}`;
- } catch (error) {
- return `Error retrieving authenticated user account details: ${error}`;
- }
-}
-
-/**
- * Account Details Action
- */
-export class AccountDetailsAction implements TwitterAction {
- public name = "account_details";
- public description = ACCOUNT_DETAILS_PROMPT;
- public argsSchema = AccountDetailsInput;
- public func = accountDetails;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/account_mentions.ts b/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/account_mentions.ts
deleted file mode 100644
index 46f1017b6..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/account_mentions.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * This module provides functionality to retrieve account mentions from Twitter (X).
- */
-
-import { z } from "zod";
-import { TwitterAction } from "./twitter_action";
-import { TwitterApi } from "twitter-api-v2";
-
-/**
- * Prompt message describing the account mentions tool.
- * A successful response will return a message with the API response in JSON format,
- * while a failure response will indicate an error from the Twitter API.
- */
-const ACCOUNT_MENTIONS_PROMPT = `
-This tool will return mentions for the specified Twitter (X) user id.
-
-A successful response will return a message with the API response as a JSON payload:
- {"data": [{"id": "1857479287504584856", "text": "@CDPAgentKit reply"}]}
-
-A failure response will return a message with the Twitter API request error:
- Error retrieving user mentions: 429 Too Many Requests
-`;
-
-/**
- * Input argument schema for the account mentions action.
- */
-export const AccountMentionsInput = z
- .object({
- userId: z
- .string()
- .min(1, "Account ID is required.")
- .describe("The Twitter (X) user id to return mentions for"),
- })
- .strip()
- .describe("Input schema for retrieving account mentions");
-
-/**
- * Retrieves mentions for a specified Twitter (X) user.
- *
- * @param client - The Twitter (X) client used to authenticate with.
- * @param args - The input arguments for the action.
- * @returns A message indicating the success or failure of the mention retrieval.
- */
-export async function accountMentions(
- client: TwitterApi,
- args: z.infer,
-): Promise {
- try {
- const response = await client.v2.userMentionTimeline(args.userId);
- return `Successfully retrieved account mentions:\n${JSON.stringify(response)}`;
- } catch (error) {
- return `Error retrieving authenticated account mentions: ${error}`;
- }
-}
-
-/**
- * Account Mentions Action
- */
-export class AccountMentionsAction implements TwitterAction {
- public name = "account_mentions";
- public description = ACCOUNT_MENTIONS_PROMPT;
- public argsSchema = AccountMentionsInput;
- public func = accountMentions;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/index.ts b/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/index.ts
deleted file mode 100644
index cbba20878..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/index.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * This module exports various Twitter (X) action instances and their associated types.
- */
-
-import { TwitterAction, TwitterActionSchemaAny } from "./twitter_action";
-import { AccountDetailsAction } from "./account_details";
-import { AccountMentionsAction } from "./account_mentions";
-import { PostTweetAction } from "./post_tweet";
-import { PostTweetReplyAction } from "./post_tweet_reply";
-
-/**
- * Retrieve an array of Twitter (X) action instances.
- *
- * @returns {TwitterAction[]} An array of Twitter action instances.
- */
-export function getAllTwitterActions(): TwitterAction[] {
- return [
- new AccountDetailsAction(),
- new AccountMentionsAction(),
- new PostTweetReplyAction(),
- new PostTweetAction(),
- ];
-}
-
-/**
- * All available Twitter (X) actions.
- */
-export const TWITTER_ACTIONS = getAllTwitterActions();
-
-/**
- * All Twitter (X) action types.
- */
-export {
- TwitterAction,
- TwitterActionSchemaAny,
- AccountDetailsAction,
- AccountMentionsAction,
- PostTweetAction,
- PostTweetReplyAction,
-};
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/post_tweet.ts b/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/post_tweet.ts
deleted file mode 100644
index 5d9707d03..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/post_tweet.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * This module provides functionality to post a tweet on Twitter (X).
- */
-
-import { z } from "zod";
-import { TwitterAction } from "./twitter_action";
-import { TwitterApi } from "twitter-api-v2";
-
-/**
- * Prompt message describing the post tweet tool.
- * A successful response will return a message with the API response in JSON format,
- * while a failure response will indicate an error from the Twitter API.
- */
-const POST_TWEET_PROMPT = `
-This tool will post a tweet on Twitter. The tool takes the text of the tweet as input. Tweets can be maximum 280 characters.
-
-A successful response will return a message with the API response as a JSON payload:
- {"data": {"text": "hello, world!", "id": "0123456789012345678", "edit_history_tweet_ids": ["0123456789012345678"]}}
-
-A failure response will return a message with the Twitter API request error:
- You are not allowed to create a Tweet with duplicate content.
-`;
-
-/**
- * Input argument schema for the post tweet action.
- */
-export const PostTweetInput = z
- .object({
- tweet: z.string().max(280, "Tweet must be a maximum of 280 characters."),
- })
- .strip()
- .describe("Input schema for posting a tweet");
-
-/**
- * Posts a tweet on Twitter (X).
- *
- * @param client - The Twitter (X) client used to authenticate with.
- * @param args - The input arguments for the action.
- * @returns A message indicating the success or failure of the tweet posting.
- */
-export async function postTweet(
- client: TwitterApi,
- args: z.infer,
-): Promise {
- try {
- const response = await client.v2.tweet(args.tweet);
- return `Successfully posted to Twitter:\n${JSON.stringify(response)}`;
- } catch (error) {
- return `Error posting to Twitter:\n${error}`;
- }
-}
-
-/**
- * Post Tweet Action
- */
-export class PostTweetAction implements TwitterAction {
- public name = "post_tweet";
- public description = POST_TWEET_PROMPT;
- public argsSchema = PostTweetInput;
- public func = postTweet;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/post_tweet_reply.ts b/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/post_tweet_reply.ts
deleted file mode 100644
index 139e4cd5f..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/post_tweet_reply.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * This module provides functionality to post a reply to a tweet on Twitter (X).
- */
-
-import { z } from "zod";
-import { TwitterAction } from "./twitter_action";
-import { TwitterApi } from "twitter-api-v2";
-
-/**
- * Prompt message describing the post tweet reply tool.
- * A successful response will return a message with the API response in JSON format,
- * while a failure response will indicate an error from the Twitter API.
- */
-const POST_TWEET_REPLY_PROMPT = `
-This tool will post a tweet on Twitter. The tool takes the text of the tweet as input. Tweets can be maximum 280 characters.
-
-A successful response will return a message with the API response as a JSON payload:
- {"data": {"text": "hello, world!", "id": "0123456789012345678", "edit_history_tweet_ids": ["0123456789012345678"]}}
-
-A failure response will return a message with the Twitter API request error:
- You are not allowed to create a Tweet with duplicate content.
-`;
-
-/**
- * Input argument schema for the post tweet reply action.
- */
-export const PostTweetReplyInput = z
- .object({
- tweetId: z.string().describe("The id of the tweet to reply to"),
- tweetReply: z
- .string()
- .max(280, "The reply to the tweet which must be a maximum of 280 characters."),
- })
- .strip()
- .describe("Input schema for posting a tweet reply");
-
-/**
- * Posts a reply to a specified tweet on Twitter (X).
- *
- * @param client - The Twitter (X) client used to authenticate with.
- * @param args - The input arguments for the action.
- * @returns A message indicating the success or failure of the reply posting.
- */
-export async function postTweet(
- client: TwitterApi,
- args: z.infer,
-): Promise {
- try {
- const response = await client.v2.tweet(args.tweetReply, {
- reply: { in_reply_to_tweet_id: args.tweetId },
- });
-
- return `Successfully posted reply to Twitter:\n${JSON.stringify(response)}`;
- } catch (error) {
- return `Error posting reply to Twitter: ${error}`;
- }
-}
-
-/**
- * Post Tweet Reply Action
- */
-export class PostTweetReplyAction implements TwitterAction {
- public name = "post_tweet_reply";
- public description = POST_TWEET_REPLY_PROMPT;
- public argsSchema = PostTweetReplyInput;
- public func = postTweet;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/twitter_action.ts b/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/twitter_action.ts
deleted file mode 100644
index 026e1e598..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/social/twitter/twitter_action.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { z } from "zod";
-import { TwitterApi } from "twitter-api-v2";
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export type TwitterActionSchemaAny = z.ZodObject;
-
-/**
- * Represents the base structure for Twitter (X) Actions.
- */
-export interface TwitterAction {
- /**
- * The name of the action.
- */
- name: string;
-
- /**
- * A description of what the action does
- */
- description: string;
-
- /**
- * Schema for validating action arguments
- */
- argsSchema: TActionSchema;
-
- /**
- * The function to execute for this action
- */
- func:
- | ((client: TwitterApi, args: z.infer) => Promise)
- | ((args: z.infer) => Promise);
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/trade.ts b/cdp-agentkit-core/typescript/src/actions/cdp/trade.ts
deleted file mode 100644
index 58f81ba2e..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/trade.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import { CdpAction } from "./cdp_action";
-import { Wallet, Amount } from "@coinbase/coinbase-sdk";
-import { z } from "zod";
-
-const TRADE_PROMPT = `
-This tool will trade a specified amount of a 'from asset' to a 'to asset' for the wallet.
-
-It takes the following inputs:
-- The amount of the 'from asset' to trade
-- The from asset ID to trade
-- The asset ID to receive from the trade
-
-Important notes:
-- Trades are only supported on mainnet networks (ie, 'base-mainnet', 'base', 'ethereum-mainnet', 'ethereum', etc.)
-- Never allow trades on any non-mainnet network (ie, 'base-sepolia', 'ethereum-sepolia', etc.)
-- When selling a native asset (e.g. 'eth' on base-mainnet), ensure there is sufficient balance to pay for the trade AND the gas cost of this trade
-`;
-
-/**
- * Input schema for trade action.
- */
-export const TradeInput = z
- .object({
- amount: z.custom().describe("The amount of the from asset to trade"),
- fromAssetId: z.string().describe("The from asset ID to trade"),
- toAssetId: z.string().describe("The to asset ID to receive from the trade"),
- })
- .strip()
- .describe("Instructions for trading assets");
-
-/**
- * Trades a specified amount of a from asset to a to asset for the wallet.
- *
- * @param wallet - The wallet to trade the asset from.
- * @param args - The input arguments for the action.
- * @returns A message containing the trade details.
- */
-export async function trade(wallet: Wallet, args: z.infer): Promise {
- try {
- const tradeResult = await wallet.createTrade({
- amount: args.amount,
- fromAssetId: args.fromAssetId,
- toAssetId: args.toAssetId,
- });
-
- const result = await tradeResult.wait();
-
- return `Traded ${args.amount} of ${args.fromAssetId} for ${result.getToAmount()} of ${
- args.toAssetId
- }.\nTransaction hash for the trade: ${result
- .getTransaction()
- .getTransactionHash()}\nTransaction link for the trade: ${result
- .getTransaction()
- .getTransactionLink()}`;
- } catch (error) {
- return `Error trading assets: ${error}`;
- }
-}
-
-/**
- * Trade action.
- */
-export class TradeAction implements CdpAction {
- public name = "trade";
- public description = TRADE_PROMPT;
- public argsSchema = TradeInput;
- public func = trade;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/transfer.ts b/cdp-agentkit-core/typescript/src/actions/cdp/transfer.ts
deleted file mode 100644
index 577998b98..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/transfer.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import { CdpAction } from "./cdp_action";
-import { Wallet, Amount } from "@coinbase/coinbase-sdk";
-import { z } from "zod";
-
-const TRANSFER_PROMPT = `
-This tool will transfer an asset from the wallet to another onchain address.
-
-It takes the following inputs:
-- amount: The amount to transfer
-- assetId: The asset ID to transfer
-- destination: Where to send the funds (can be an onchain address, ENS 'example.eth', or Basename 'example.base.eth')
-- gasless: Whether to do a gasless transfer
-
-Important notes:
-- Gasless transfers are only available on base-sepolia and base-mainnet (base) networks for 'usdc' asset
-- Always use gasless transfers when available
-- Always use asset ID 'usdc' when transferring USDC
-- Ensure sufficient balance of the input asset before transferring
-- When sending native assets (e.g. 'eth' on base-mainnet), ensure there is sufficient balance for the transfer itself AND the gas cost of this transfer
-`;
-
-/**
- * Input schema for transfer action.
- */
-export const TransferInput = z
- .object({
- amount: z.custom().describe("The amount of the asset to transfer"),
- assetId: z.string().describe("The asset ID to transfer"),
- destination: z.string().describe("The destination to transfer the funds"),
- gasless: z.boolean().default(false).describe("Whether to do a gasless transfer"),
- })
- .strip()
- .describe("Instructions for transferring assets");
-
-/**
- * Transfers a specified amount of an asset to a destination onchain.
- *
- * @param wallet - The wallet to transfer the asset from.
- * @param args - The input arguments for the action.
- * @returns A message containing the transfer details.
- */
-export async function transfer(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- try {
- const transferResult = await wallet.createTransfer({
- amount: args.amount,
- assetId: args.assetId,
- destination: args.destination,
- gasless: args.gasless,
- });
-
- const result = await transferResult.wait();
-
- return `Transferred ${args.amount} of ${args.assetId} to ${
- args.destination
- }.\nTransaction hash for the transfer: ${result.getTransactionHash()}\nTransaction link for the transfer: ${result.getTransactionLink()}`;
- } catch (error) {
- return `Error transferring the asset: ${error}`;
- }
-}
-
-/**
- * Transfer action.
- */
-export class TransferAction implements CdpAction {
- public name = "transfer";
- public description = TRANSFER_PROMPT;
- public argsSchema = TransferInput;
- public func = transfer;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/transfer_nft.ts b/cdp-agentkit-core/typescript/src/actions/cdp/transfer_nft.ts
deleted file mode 100644
index 9819e9b55..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/transfer_nft.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import { CdpAction } from "./cdp_action";
-import { Wallet } from "@coinbase/coinbase-sdk";
-import { z } from "zod";
-
-const TRANSFER_NFT_PROMPT = `
-This tool will transfer an NFT (ERC721 token) from the wallet to another onchain address.
-
-It takes the following inputs:
-- contractAddress: The NFT contract address
-- tokenId: The ID of the specific NFT to transfer
-- destination: Where to send the NFT (can be an onchain address, ENS 'example.eth', or Basename 'example.base.eth')
-
-Important notes:
-- Ensure you have ownership of the NFT before attempting transfer
-- Ensure there is sufficient native token balance for gas fees
-- The wallet must either own the NFT or have approval to transfer it
-`;
-
-/**
- * Input schema for NFT transfer action.
- */
-export const TransferNftInput = z
- .object({
- contractAddress: z.string().describe("The NFT contract address to interact with"),
- tokenId: z.string().describe("The ID of the NFT to transfer"),
- destination: z
- .string()
- .describe(
- "The destination to transfer the NFT, e.g. `0x58dBecc0894Ab4C24F98a0e684c989eD07e4e027`, `example.eth`, `example.base.eth`",
- ),
- fromAddress: z
- .string()
- .optional()
- .describe(
- "The address to transfer from. If not provided, defaults to the wallet's default address",
- ),
- })
- .strip()
- .describe("Input schema for transferring an NFT");
-
-/**
- * Transfers an NFT (ERC721 token) to a destination address.
- *
- * @param wallet - The wallet to transfer the NFT from.
- * @param args - The input arguments for the action.
- * @returns A message containing the transfer details.
- */
-export async function transferNft(
- wallet: Wallet,
- args: z.infer,
-): Promise {
- const from = args.fromAddress || (await wallet.getDefaultAddress()).getId();
-
- try {
- const transferResult = await wallet.invokeContract({
- contractAddress: args.contractAddress,
- method: "transferFrom",
- args: {
- from,
- to: args.destination,
- tokenId: args.tokenId,
- },
- });
-
- const result = await transferResult.wait();
-
- const transaction = result.getTransaction();
-
- return `Transferred NFT (ID: ${args.tokenId}) from contract ${args.contractAddress} to ${
- args.destination
- }.\nTransaction hash: ${transaction.getTransactionHash()}\nTransaction link: ${transaction.getTransactionLink()}`;
- } catch (error) {
- return `Error transferring the NFT (contract: ${args.contractAddress}, ID: ${args.tokenId}) from ${from} to ${args.destination}): ${error}`;
- }
-}
-
-/**
- * Transfer NFT action.
- */
-export class TransferNftAction implements CdpAction {
- name = "transfer_nft";
- description = TRANSFER_NFT_PROMPT;
- argsSchema = TransferNftInput;
- func = transferNft;
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/utils.ts b/cdp-agentkit-core/typescript/src/actions/cdp/utils.ts
deleted file mode 100644
index 940438256..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/utils.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { Wallet } from "@coinbase/coinbase-sdk";
-
-import { ERC20_APPROVE_ABI } from "./constants";
-
-/**
- * Approve a spender to spend a specified amount of tokens.
- * @param wallet - The wallet to execute the approval from
- * @param tokenAddress - The address of the token contract
- * @param spender - The address of the spender
- * @param amount - The amount of tokens to approve
- * @returns A success message with transaction hash or error message
- */
-export async function approve(
- wallet: Wallet,
- tokenAddress: string,
- spender: string,
- amount: bigint,
-): Promise {
- try {
- const invocation = await wallet.invokeContract({
- contractAddress: tokenAddress,
- method: "approve",
- abi: ERC20_APPROVE_ABI,
- args: {
- spender: spender,
- value: amount.toString(),
- },
- });
-
- const result = await invocation.wait();
-
- return `Approved ${amount} tokens for ${spender} with transaction hash: ${result.getTransactionHash()}`;
- } catch (error) {
- return `Error approving tokens: ${error}`;
- }
-}
diff --git a/cdp-agentkit-core/typescript/src/actions/cdp/wrap_eth.ts b/cdp-agentkit-core/typescript/src/actions/cdp/wrap_eth.ts
deleted file mode 100644
index aba86c2ec..000000000
--- a/cdp-agentkit-core/typescript/src/actions/cdp/wrap_eth.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import { CdpAction } from "./cdp_action";
-import { Wallet } from "@coinbase/coinbase-sdk";
-import { z } from "zod";
-
-export const WETH_ADDRESS = "0x4200000000000000000000000000000000000006";
-
-export const WETH_ABI = [
- {
- inputs: [],
- name: "deposit",
- outputs: [],
- stateMutability: "payable",
- type: "function",
- },
- {
- inputs: [
- {
- name: "account",
- type: "address",
- },
- ],
- name: "balanceOf",
- outputs: [
- {
- type: "uint256",
- },
- ],
- stateMutability: "view",
- type: "function",
- },
-];
-
-const WRAP_ETH_PROMPT = `
-This tool can only be used to wrap ETH to WETH.
-Do not use this tool for any other purpose, or trading other assets.
-
-Inputs:
-- Amount of ETH to wrap.
-
-Important notes:
-- The amount is a string and cannot have any decimal points, since the unit of measurement is wei.
-- 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 WETH
-- Minimum purchase amount is 100000000000000 wei (0.0000001 WETH)
-- Only supported on the following networks:
- - Base Sepolia (ie, 'base-sepolia')
- - Base Mainnet (ie, 'base', 'base-mainnet')
-`;
-
-export const WrapEthInput = z
- .object({
- amountToWrap: z.string().describe("Amount of ETH to wrap in wei"),
- })
- .strip()
- .describe("Instructions for wrapping ETH to WETH");
-
-/**
- * Wraps ETH to WETH
- *
- * @param wallet - The wallet to create the token from.
- * @param args - The input arguments for the action.
- * @returns A message containing the wrapped ETH details.
- */
-export async function wrapEth(wallet: Wallet, args: z.infer): Promise {
- try {
- const invocation = await wallet.invokeContract({
- contractAddress: WETH_ADDRESS,
- method: "deposit",
- abi: WETH_ABI,
- args: {},
- amount: BigInt(args.amountToWrap),
- assetId: "wei",
- });
- const result = await invocation.wait();
- return `Wrapped ETH with transaction hash: ${result.getTransaction().getTransactionHash()}`;
- } catch (error) {
- return `Error wrapping ETH: ${error}`;
- }
-}
-
-/**
- * Wrap ETH to WETH on Base action.
- */
-export class WrapEthAction implements CdpAction {
- public name = "wrap_eth";
- public description = WRAP_ETH_PROMPT;
- public argsSchema = WrapEthInput;
- public func = wrapEth;
-}
diff --git a/cdp-agentkit-core/typescript/src/cdp_agentkit.ts b/cdp-agentkit-core/typescript/src/cdp_agentkit.ts
deleted file mode 100644
index 49614f380..000000000
--- a/cdp-agentkit-core/typescript/src/cdp_agentkit.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-import { Coinbase, MnemonicSeedPhrase, Wallet, WalletData } from "@coinbase/coinbase-sdk";
-import { version } from "../package.json";
-import { CdpAction, CdpActionSchemaAny } from "./actions/cdp/cdp_action";
-import { z } from "zod";
-
-/**
- * Configuration options for the CDP Agentkit
- */
-interface CdpAgentkitOptions {
- cdpApiKeyName?: string;
- cdpApiKeyPrivateKey?: string;
- source?: string;
- sourceVersion?: string;
-}
-
-/**
- * Configuration options for the CDP Agentkit with a Wallet.
- */
-interface ConfigureCdpAgentkitWithWalletOptions extends CdpAgentkitOptions {
- networkId?: string;
- cdpWalletData?: string;
- mnemonicPhrase?: string;
-}
-
-/**
- * CDP Agentkit
- */
-export class CdpAgentkit {
- private wallet?: Wallet;
-
- /**
- * Initializes a new CDP Agentkit instance
- *
- * @param config - Configuration options for the CDP Agentkit
- */
- public constructor(config: CdpAgentkitOptions = {}) {
- const cdpApiKeyName = config.cdpApiKeyName || process.env.CDP_API_KEY_NAME;
- const cdpApiKeyPrivateKey = config.cdpApiKeyPrivateKey || process.env.CDP_API_KEY_PRIVATE_KEY;
- const source = config.source;
- const sourceVersion = config.sourceVersion;
-
- if (!cdpApiKeyName) {
- throw new Error("CDP_API_KEY_NAME is required but not provided");
- }
- if (!cdpApiKeyPrivateKey) {
- throw new Error("CDP_API_KEY_PRIVATE_KEY is required but not provided");
- }
-
- // Configure CDP SDK
- Coinbase.configure({
- apiKeyName: cdpApiKeyName,
- privateKey: cdpApiKeyPrivateKey.replace(/\\n/g, "\n"),
- source: source || "agentkit-core",
- sourceVersion: sourceVersion || version,
- });
- }
-
- /**
- * Configures CDP Agentkit with a Wallet.
- *
- * @param config - Optional configuration parameters
- * @returns A Promise that resolves to a new CdpAgentkit instance
- * @throws Error if required environment variables are missing or wallet initialization fails
- */
- public static async configureWithWallet(
- config: ConfigureCdpAgentkitWithWalletOptions = {},
- ): Promise {
- const agentkit = new CdpAgentkit(config);
-
- const mnemonicPhrase = config.mnemonicPhrase || process.env.MNEMONIC_PHRASE;
- const networkId = config.networkId || process.env.NETWORK_ID || Coinbase.networks.BaseSepolia;
-
- try {
- if (config.cdpWalletData) {
- const walletData = JSON.parse(config.cdpWalletData) as WalletData;
- agentkit.wallet = await Wallet.import(walletData);
- } else if (mnemonicPhrase) {
- agentkit.wallet = await Wallet.import({ mnemonicPhrase: mnemonicPhrase }, networkId);
- } else {
- agentkit.wallet = await Wallet.create({ networkId: networkId });
- }
- } catch (error) {
- throw new Error(`Failed to initialize wallet: ${error}`);
- }
-
- return agentkit;
- }
-
- /**
- * Executes a CDP action
- *
- * @param action - The CDP action to execute
- * @param args - Arguments for the action
- * @returns Result of the action execution
- * @throws Error if action execution fails
- */
- async run(
- action: CdpAction,
- args: TActionSchema,
- ): Promise {
- if (action.func.length > 1) {
- if (!this.wallet) {
- return `Unable to run CDP Action: ${action.name}. A Wallet is required. Please configure CDP Agentkit with a Wallet to run this action.`;
- }
-
- return await action.func(this.wallet!, args);
- }
-
- return await (action.func as (args: z.infer) => Promise)(args);
- }
-
- /**
- * Exports wallet data required to re-instantiate the wallet
- *
- * @returns JSON string of wallet data including wallet_id and seed
- */
- async exportWallet(): Promise {
- if (!this.wallet) {
- throw Error("Unable to export wallet. Agentkit is not configured with a wallet.");
- }
-
- const walletData = this.wallet.export();
- return JSON.stringify({
- ...walletData,
- defaultAddressId: (await this.wallet.getDefaultAddress()).getId(),
- });
- }
-}
diff --git a/cdp-agentkit-core/typescript/src/farcaster_agentkit.ts b/cdp-agentkit-core/typescript/src/farcaster_agentkit.ts
deleted file mode 100644
index ac266996a..000000000
--- a/cdp-agentkit-core/typescript/src/farcaster_agentkit.ts
+++ /dev/null
@@ -1,103 +0,0 @@
-import { z } from "zod";
-import { FarcasterAction, FarcasterActionSchemaAny } from "./actions/cdp/social/farcaster";
-
-/**
- * Schema for the options required to initialize the FarcasterAgentkit.
- */
-export const FarcasterAgentkitOptions = z
- .object({
- apiKey: z
- .string()
- .min(1, "The Neynar API key for Farcaster is required")
- .describe("The Neynar API key for Farcaster"),
- managedSigner: z
- .string()
- .min(1, "The Neynar Managed Signer UUID for Farcaster is required")
- .describe("The Neynar Managed Signer UUID for Farcaster"),
- })
- .strip()
- .describe("Options for initializing FarcasterAgentkit");
-
-/**
- * Schema for the environment variables required for FarcasterAgentkit.
- */
-const EnvSchema = z.object({
- NEYNAR_API_KEY: z
- .string()
- .min(1, "NEYNAR_API_KEY is required")
- .describe("The Neynar API key for Farcaster"),
- NEYNAR_MANAGED_SIGNER: z
- .string()
- .min(1, "NEYNAR_MANAGED_SIGNER is required")
- .describe("The Neynar Managed Signer UUID for Farcaster"),
-});
-
-/**
- * Farcaster Agentkit
- */
-export class FarcasterAgentkit {
- private config: z.infer;
-
- /**
- * Initializes a new instance of FarcasterAgentkit with the provided options.
- * If no options are provided, it attempts to load the required environment variables.
- *
- * @param options - Optional. The configuration options for the FarcasterAgentkit.
- * @throws An error if the provided options are invalid or if the environment variables cannot be loaded.
- */
- public constructor(options?: z.infer) {
- try {
- const env = EnvSchema.parse(process.env);
-
- options = {
- apiKey: options?.apiKey || env.NEYNAR_API_KEY!,
- managedSigner: options?.managedSigner || env.NEYNAR_MANAGED_SIGNER!,
- };
- } catch (error) {
- if (error instanceof z.ZodError) {
- error.errors.forEach(err => console.log(`Error: ${err.path[0]} is required`));
- }
- throw new Error("Farcaster config could not be loaded.");
- }
-
- if (!this.validateOptions(options)) {
- throw new Error("Farcaster Agentkit options could not be validated.");
- }
-
- this.config = options;
- }
-
- /**
- * Validates the provided options for the FarcasterAgentkit.
- *
- * @param options - The options to validate.
- * @returns True if the options are valid, otherwise false.
- */
- validateOptions(options: z.infer): boolean {
- try {
- FarcasterAgentkitOptions.parse(options);
- } catch (error) {
- if (error instanceof z.ZodError) {
- error.errors.forEach(err => console.log("Error:", err.message));
- }
-
- return false;
- }
-
- return true;
- }
-
- /**
- * Executes a Farcaster action.
- *
- * @param action - The Farcaster action to execute.
- * @param args - The arguments for the action.
- * @returns The result of the execution.
- */
- async run(
- action: FarcasterAction,
- args: TActionSchema,
- ): Promise {
- return await action.func(args);
- }
-}
diff --git a/cdp-agentkit-core/typescript/src/index.ts b/cdp-agentkit-core/typescript/src/index.ts
deleted file mode 100644
index fd6965370..000000000
--- a/cdp-agentkit-core/typescript/src/index.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-// Export CDP actions
-export * from "./actions/cdp";
-
-// Export CDP DeFi actions
-export * from "./actions/cdp/defi/wow";
-
-// Export Farcaster actions
-export * from "./actions/cdp/social/farcaster";
-
-// Export Twitter actions
-export * from "./actions/cdp/social/twitter";
-
-// Export CDP Action
-export { CdpAction } from "./actions/cdp/cdp_action";
-
-// Export CDP AgentKit
-export { CdpAgentkit } from "./cdp_agentkit";
-
-// Export Farcaster AgentKit
-export { FarcasterAgentkit } from "./farcaster_agentkit";
-
-// Export Twitter AgentKit
-export { TwitterAgentkit } from "./twitter_agentkit";
diff --git a/cdp-agentkit-core/typescript/src/tests/address_reputation_test.ts b/cdp-agentkit-core/typescript/src/tests/address_reputation_test.ts
deleted file mode 100644
index 640826622..000000000
--- a/cdp-agentkit-core/typescript/src/tests/address_reputation_test.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-import { Address } from "@coinbase/coinbase-sdk";
-import { AddressReputationAction } from "../actions/cdp/address_reputation";
-
-const MOCK_ADDRESS = "0x1234567890123456789012345678901234567890";
-const MOCK_NETWORK = "base-sepolia";
-
-jest.mock("@coinbase/coinbase-sdk", () => ({
- Address: jest.fn(),
-}));
-
-describe("Address Reputation Input", () => {
- const action = new AddressReputationAction();
-
- it("should successfully parse valid input", () => {
- const validInput = {
- network: MOCK_NETWORK,
- address: MOCK_ADDRESS,
- };
-
- const result = action.argsSchema.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = action.argsSchema.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-
- it("should fail with invalid address", () => {
- const invalidInput = {
- network: MOCK_NETWORK,
- address: "not_an_address",
- };
- const result = action.argsSchema.safeParse(invalidInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Address Reputation Action", () => {
- let mockAddress: jest.Mocked;
-
- beforeEach(() => {
- mockAddress = {
- reputation: jest.fn(),
- } as unknown as jest.Mocked;
-
- (Address as unknown as jest.Mock).mockImplementation(() => mockAddress);
- });
-
- it("should successfully check address reputation", async () => {
- const mockReputation = {
- score: 85,
- metadata: {
- total_transactions: 150,
- unique_days_active: 30,
- longest_active_streak: 10,
- current_active_streak: 5,
- activity_period_days: 45,
- token_swaps_performed: 20,
- bridge_transactions_performed: 5,
- lend_borrow_stake_transactions: 10,
- ens_contract_interactions: 2,
- smart_contract_deployments: 1,
- },
-
- // TODO: remove this once AddressReputation is exported from the sdk
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- } as unknown as jest.Mocked;
-
- mockAddress.reputation.mockResolvedValue(mockReputation);
-
- const args = {
- network: MOCK_NETWORK,
- address: MOCK_ADDRESS,
- };
-
- const action = new AddressReputationAction();
- const response = await action.func(args);
-
- expect(response).toBe(mockReputation.toString());
- });
-
- it("should handle errors gracefully", async () => {
- const error = new Error("API error");
- mockAddress.reputation.mockRejectedValue(error);
-
- const args = {
- network: MOCK_NETWORK,
- address: MOCK_ADDRESS,
- };
-
- const action = new AddressReputationAction();
- const response = await action.func(args);
-
- expect(response).toBe(`Error checking address reputation: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/cdp_agentkit_test.ts b/cdp-agentkit-core/typescript/src/tests/cdp_agentkit_test.ts
deleted file mode 100644
index ebb79618f..000000000
--- a/cdp-agentkit-core/typescript/src/tests/cdp_agentkit_test.ts
+++ /dev/null
@@ -1,117 +0,0 @@
-import { Coinbase, Wallet, WalletData } from "@coinbase/coinbase-sdk";
-import { CdpAgentkit } from "../cdp_agentkit";
-
-const MOCK_MNEMONIC_PHRASE =
- "eternal phone creek robot disorder climb thought eternal noodle flat cage bubble liquid sting can";
-const MOCK_WALLET_ID = "0x123456789abcdef";
-const MOCK_WALLET_SEED = "0xc746290109d0b86162c428be6e27f552";
-const MOCK_WALLET_JSON = `{"defaultAddressId":"0xabcdef123456789", "seed":"${MOCK_WALLET_SEED}", "walletId":"${MOCK_WALLET_ID}"}`;
-
-describe("CdpAgentkit", () => {
- describe("initialization", () => {
- const mockWallet: jest.Mocked = {} as unknown as jest.Mocked;
-
- beforeEach(async () => {
- process.env.CDP_API_KEY_NAME = "test-key";
- process.env.CDP_API_KEY_PRIVATE_KEY = "test-private-key";
-
- jest.spyOn(Wallet, "create").mockResolvedValue(mockWallet);
- });
-
- afterEach(() => {
- jest.resetAllMocks();
-
- process.env.CDP_API_KEY_NAME = "";
- process.env.CDP_API_KEY_PRIVATE_KEY = "";
- });
-
- it("should successfully init with env", async () => {
- const options = {};
- const result = await CdpAgentkit.configureWithWallet(options);
-
- expect(result).toBeDefined();
- expect(Wallet.create).toHaveBeenCalledWith({
- networkId: Coinbase.networks.BaseSepolia,
- });
- });
-
- it("should successfully init with options and without env", async () => {
- const options = {
- cdpApiKeyName: "test-key",
- cdpApiKeyPrivateKey: "test-private-key",
- };
-
- process.env.CDP_API_KEY_NAME = "";
- process.env.CDP_API_KEY_PRIVATE_KEY = "";
-
- const result = await CdpAgentkit.configureWithWallet(options);
-
- expect(result).toBeDefined();
- expect(Wallet.create).toHaveBeenCalledWith({
- networkId: Coinbase.networks.BaseSepolia,
- });
- });
-
- it("should successfully init with wallet data", async () => {
- const options = {
- cdpWalletData: MOCK_WALLET_JSON,
- };
-
- jest.spyOn(Wallet, "import").mockResolvedValue(mockWallet);
-
- const result = await CdpAgentkit.configureWithWallet(options);
-
- expect(result).toBeDefined();
- expect(Wallet.import).toHaveBeenCalledWith(JSON.parse(MOCK_WALLET_JSON) as WalletData);
- });
-
- it("should successfully init with mnemonic Phrase ", async () => {
- const networkId = Coinbase.networks.BaseSepolia;
-
- const options = {
- mnemonicPhrase: MOCK_MNEMONIC_PHRASE,
- };
-
- jest.spyOn(Wallet, "import").mockResolvedValue(mockWallet);
-
- const result = await CdpAgentkit.configureWithWallet(options);
-
- expect(result).toBeDefined();
- expect(Wallet.import).toHaveBeenCalledWith(
- { mnemonicPhrase: MOCK_MNEMONIC_PHRASE },
- networkId,
- );
- });
-
- it("should successfully init with mnemonic Phrase ", async () => {
- const networkId = Coinbase.networks.BaseMainnet;
-
- const options = {
- mnemonicPhrase: MOCK_MNEMONIC_PHRASE,
- networkId,
- };
-
- jest.spyOn(Wallet, "import").mockResolvedValue(mockWallet);
-
- const result = await CdpAgentkit.configureWithWallet(options);
-
- expect(result).toBeDefined();
- expect(Wallet.import).toHaveBeenCalledWith(
- { mnemonicPhrase: MOCK_MNEMONIC_PHRASE },
- networkId,
- );
- });
-
- it("should fail init without env", async () => {
- const options = {};
-
- process.env.CDP_API_KEY_NAME = "";
- process.env.CDP_API_KEY_PRIVATE_KEY = "";
-
- await expect(CdpAgentkit.configureWithWallet(options)).rejects.toThrow(
- "CDP_API_KEY_NAME is required but not provided",
- );
- expect(Wallet.create).not.toHaveBeenCalled();
- });
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/data_pyth_fetch_price_feed_id_test.ts b/cdp-agentkit-core/typescript/src/tests/data_pyth_fetch_price_feed_id_test.ts
deleted file mode 100644
index b0c213f2b..000000000
--- a/cdp-agentkit-core/typescript/src/tests/data_pyth_fetch_price_feed_id_test.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import {
- PythFetchPriceFeedIDInput,
- pythFetchPriceFeedID,
-} from "../actions/cdp/data/pyth/fetch_price_feed_id";
-
-const MOCK_TOKEN_SYMBOL = "BTC";
-
-describe("Pyth Fetch Price Feed ID Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- tokenSymbol: MOCK_TOKEN_SYMBOL,
- };
-
- const result = PythFetchPriceFeedIDInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = PythFetchPriceFeedIDInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Pyth Fetch Price Feed ID Action", () => {
- beforeEach(() => {
- global.fetch = jest.fn();
- });
-
- it("successfully fetches price feed ID for a token", async () => {
- const mockResponse = [
- {
- id: "0ff1e87c65eb6e6f7768e66543859b7f3076ba8a3529636f6b2664f367c3344a",
- type: "price_feed",
- attributes: {
- base: "BTC",
- quote: "USD",
- asset_type: "crypto",
- },
- },
- ];
-
- (global.fetch as jest.Mock).mockResolvedValue({
- ok: true,
- json: async () => mockResponse,
- });
-
- const result = await pythFetchPriceFeedID({ tokenSymbol: MOCK_TOKEN_SYMBOL });
-
- // Verify the result
- expect(result).toBe("0ff1e87c65eb6e6f7768e66543859b7f3076ba8a3529636f6b2664f367c3344a");
-
- // Verify fetch was called with correct URL
- expect(global.fetch).toHaveBeenCalledWith(
- "https://hermes.pyth.network/v2/price_feeds?query=BTC&asset_type=crypto",
- );
- });
-
- it("throws error when HTTP request fails", async () => {
- (global.fetch as jest.Mock).mockResolvedValue({
- ok: false,
- status: 404,
- });
-
- await expect(pythFetchPriceFeedID({ tokenSymbol: MOCK_TOKEN_SYMBOL })).rejects.toThrow(
- "HTTP error! status: 404",
- );
- });
-
- it("throws error when no data is returned", async () => {
- (global.fetch as jest.Mock).mockResolvedValue({
- ok: true,
- json: async () => [],
- });
-
- await expect(pythFetchPriceFeedID({ tokenSymbol: "INVALID" })).rejects.toThrow(
- "No price feed found for INVALID",
- );
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/data_pyth_fetch_price_test.ts b/cdp-agentkit-core/typescript/src/tests/data_pyth_fetch_price_test.ts
deleted file mode 100644
index de6e725b8..000000000
--- a/cdp-agentkit-core/typescript/src/tests/data_pyth_fetch_price_test.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import { PythFetchPriceInput, pythFetchPrice } from "../actions/cdp/data/pyth/fetch_price";
-
-const MOCK_PRICE_FEED_ID = "valid-price-feed-id";
-
-describe("Pyth Fetch Price Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- priceFeedID: MOCK_PRICE_FEED_ID,
- };
-
- const result = PythFetchPriceInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = PythFetchPriceInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Pyth Fetch Price Action", () => {
- beforeEach(() => {
- global.fetch = jest.fn();
- });
-
- it("successfully fetches and formats price with decimal places", async () => {
- const mockResponse = {
- parsed: [
- {
- price: {
- price: "4212345",
- expo: -2,
- conf: "1234",
- },
- id: MOCK_PRICE_FEED_ID,
- },
- ],
- };
-
- (global.fetch as jest.Mock).mockResolvedValue({
- ok: true,
- json: async () => mockResponse,
- });
-
- const result = await pythFetchPrice({ priceFeedID: MOCK_PRICE_FEED_ID });
-
- expect(result).toBe("42123.45");
-
- expect(global.fetch).toHaveBeenCalledWith(
- `https://hermes.pyth.network/v2/updates/price/latest?ids[]=${MOCK_PRICE_FEED_ID}`,
- );
- });
-
- it("throws error when HTTP request fails", async () => {
- (global.fetch as jest.Mock).mockResolvedValue({
- ok: false,
- status: 404,
- });
-
- await expect(pythFetchPrice({ priceFeedID: MOCK_PRICE_FEED_ID })).rejects.toThrow(
- "HTTP error! status: 404",
- );
- });
-
- it("throws error when no parsed data is available", async () => {
- const mockResponse = {
- parsed: [],
- };
-
- (global.fetch as jest.Mock).mockResolvedValue({
- ok: true,
- json: async () => mockResponse,
- });
-
- await expect(pythFetchPrice({ priceFeedID: MOCK_PRICE_FEED_ID })).rejects.toThrow(
- `No price data found for ${MOCK_PRICE_FEED_ID}`,
- );
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/defi_morpho_deposit_test.ts b/cdp-agentkit-core/typescript/src/tests/defi_morpho_deposit_test.ts
deleted file mode 100644
index bd1f2fd78..000000000
--- a/cdp-agentkit-core/typescript/src/tests/defi_morpho_deposit_test.ts
+++ /dev/null
@@ -1,199 +0,0 @@
-import { Coinbase, ContractInvocation, Wallet, Asset } from "@coinbase/coinbase-sdk";
-
-import { approve } from "../actions/cdp/utils";
-
-import { MorphoDepositAction } from "../actions/cdp/defi/morpho/deposit";
-import { METAMORPHO_ABI } from "../actions/cdp/defi/morpho/constants";
-
-const MOCK_VAULT_ADDRESS = "0x1234567890123456789012345678901234567890";
-const MOCK_ATOMIC_ASSETS = "1000000000000000000";
-const MOCK_WHOLE_ASSETS = "0.0001";
-const MOCK_RECEIVER_ID = "0x9876543210987654321098765432109876543210";
-const MOCK_TOKEN_ADDRESS = "0x4200000000000000000000000000000000000006";
-
-jest.mock("../actions/cdp/utils");
-const mockApprove = approve as jest.MockedFunction;
-
-describe("Morpho Deposit Input", () => {
- const action = new MorphoDepositAction();
-
- it("should successfully parse valid input", () => {
- const validInput = {
- vaultAddress: MOCK_VAULT_ADDRESS,
- assets: MOCK_WHOLE_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- tokenAddress: MOCK_TOKEN_ADDRESS,
- };
-
- const result = action.argsSchema.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = action.argsSchema.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-
- it("should fail with invalid vault address", () => {
- const invalidInput = {
- vaultAddress: "not_an_address",
- assets: MOCK_WHOLE_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- tokenAddress: MOCK_TOKEN_ADDRESS,
- };
- const result = action.argsSchema.safeParse(invalidInput);
-
- expect(result.success).toBe(false);
- });
-
- it("should handle valid asset string formats", () => {
- const validInput = {
- vaultAddress: MOCK_VAULT_ADDRESS,
- assets: MOCK_WHOLE_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- tokenAddress: MOCK_TOKEN_ADDRESS,
- };
-
- const validInputs = [
- { ...validInput, assets: "1000000000000000000" },
- { ...validInput, assets: "1.5" },
- { ...validInput, assets: "0.00001" },
- ];
-
- validInputs.forEach(input => {
- const result = action.argsSchema.safeParse(input);
- expect(result.success).toBe(true);
- });
- });
-
- it("should reject invalid asset strings", () => {
- const validInput = {
- vaultAddress: MOCK_VAULT_ADDRESS,
- assets: MOCK_WHOLE_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- tokenAddress: MOCK_TOKEN_ADDRESS,
- };
-
- const invalidInputs = [
- { ...validInput, assets: "" },
- { ...validInput, assets: "1,000" },
- { ...validInput, assets: "1.2.3" },
- { ...validInput, assets: "abc" },
- ];
-
- invalidInputs.forEach(input => {
- const result = action.argsSchema.safeParse(input);
- expect(result.success).toBe(false);
- });
- });
-});
-
-describe("Morpho Deposit Action", () => {
- const NETWORK_ID = Coinbase.networks.BaseSepolia;
- const TRANSACTION_HASH = "0xabcdef1234567890";
- const TRANSACTION_LINK = `https://etherscan.io/tx/${TRANSACTION_HASH}`;
-
- const action = new MorphoDepositAction();
-
- let mockContractInvocation: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockContractInvocation = {
- wait: jest.fn().mockResolvedValue({
- getTransactionHash: jest.fn().mockReturnValue(TRANSACTION_HASH),
- getTransactionLink: jest.fn().mockReturnValue(TRANSACTION_LINK),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet = {
- invokeContract: jest.fn(),
- getDefaultAddress: jest.fn().mockResolvedValue({
- getId: jest.fn().mockReturnValue(MOCK_RECEIVER_ID),
- }),
- getNetworkId: jest.fn().mockReturnValue(NETWORK_ID),
- } as unknown as jest.Mocked;
-
- mockWallet.invokeContract.mockResolvedValue(mockContractInvocation);
-
- jest.spyOn(Asset, "fetch").mockResolvedValue({
- toAtomicAmount: jest.fn().mockReturnValue(BigInt(MOCK_ATOMIC_ASSETS)),
- } as unknown as Asset);
-
- mockApprove.mockResolvedValue("Approval successful");
- });
-
- it("should successfully deposit to Morpho vault", async () => {
- const args = {
- vaultAddress: MOCK_VAULT_ADDRESS,
- assets: MOCK_WHOLE_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- tokenAddress: MOCK_TOKEN_ADDRESS,
- };
-
- const atomicAssets = BigInt(MOCK_ATOMIC_ASSETS);
- const response = await action.func(mockWallet, args);
-
- expect(mockApprove).toHaveBeenCalledWith(
- mockWallet,
- MOCK_TOKEN_ADDRESS,
- MOCK_VAULT_ADDRESS,
- atomicAssets,
- );
-
- expect(mockWallet.invokeContract).toHaveBeenCalledWith({
- contractAddress: MOCK_VAULT_ADDRESS,
- method: "deposit",
- abi: METAMORPHO_ABI,
- args: {
- assets: MOCK_ATOMIC_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- },
- });
-
- expect(mockContractInvocation.wait).toHaveBeenCalled();
- expect(response).toContain(`Deposited ${MOCK_WHOLE_ASSETS}`);
- expect(response).toContain(`to Morpho Vault ${MOCK_VAULT_ADDRESS}`);
- expect(response).toContain(`with transaction hash: ${TRANSACTION_HASH}`);
- expect(response).toContain(`and transaction link: ${TRANSACTION_LINK}`);
- });
-
- it("should handle approval failure", async () => {
- const args = {
- vaultAddress: MOCK_VAULT_ADDRESS,
- assets: MOCK_WHOLE_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- tokenAddress: MOCK_TOKEN_ADDRESS,
- };
-
- mockApprove.mockResolvedValue("Error: Approval failed");
-
- const response = await action.func(mockWallet, args);
-
- expect(mockApprove).toHaveBeenCalled();
- expect(response).toContain("Error approving Morpho Vault as spender: Error: Approval failed");
- expect(mockWallet.invokeContract).not.toHaveBeenCalled();
- });
-
- it("should handle deposit errors", async () => {
- const args = {
- vaultAddress: MOCK_VAULT_ADDRESS,
- assets: MOCK_WHOLE_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- tokenAddress: MOCK_TOKEN_ADDRESS,
- };
-
- const error = new Error("Failed to deposit to Morpho vault");
- mockWallet.invokeContract.mockRejectedValue(error);
-
- const response = await action.func(mockWallet, args);
-
- expect(mockApprove).toHaveBeenCalled();
- expect(mockWallet.invokeContract).toHaveBeenCalled();
- expect(response).toContain(`Error depositing to Morpho Vault: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/defi_morpho_withdraw_test.ts b/cdp-agentkit-core/typescript/src/tests/defi_morpho_withdraw_test.ts
deleted file mode 100644
index a9ad7d7ab..000000000
--- a/cdp-agentkit-core/typescript/src/tests/defi_morpho_withdraw_test.ts
+++ /dev/null
@@ -1,154 +0,0 @@
-import { Coinbase, ContractInvocation, Wallet } from "@coinbase/coinbase-sdk";
-import { MorphoWithdrawAction } from "../actions/cdp/defi/morpho/withdraw";
-import { METAMORPHO_ABI } from "../actions/cdp/defi/morpho/constants";
-
-const MOCK_VAULT_ADDRESS = "0x1234567890123456789012345678901234567890";
-const MOCK_ASSETS = "1000000000000000000"; // 1 token in wei
-const MOCK_RECEIVER_ID = "0x9876543210987654321098765432109876543210";
-
-describe("Morpho Withdraw Input", () => {
- const action = new MorphoWithdrawAction();
-
- it("should successfully parse valid input", () => {
- const validInput = {
- vaultAddress: MOCK_VAULT_ADDRESS,
- assets: MOCK_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- };
-
- const result = action.argsSchema.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = action.argsSchema.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-
- it("should fail with invalid Vault address", () => {
- const invalidInput = {
- vaultAddress: "not_an_address",
- assets: MOCK_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- };
- const result = action.argsSchema.safeParse(invalidInput);
-
- expect(result.success).toBe(false);
- if (!result.success) {
- expect(result.error.issues[0].path[0]).toBe("vaultAddress");
- }
- });
-
- it("should handle valid asset string formats", () => {
- const validInput = {
- vaultAddress: MOCK_VAULT_ADDRESS,
- assets: MOCK_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- };
-
- const validInputs = [{ ...validInput, assets: "1000000000000000000" }];
-
- validInputs.forEach(input => {
- const result = action.argsSchema.safeParse(input);
- expect(result.success).toBe(true);
- });
- });
-
- it("should reject invalid asset strings", () => {
- const validInput = {
- vaultAddress: MOCK_VAULT_ADDRESS,
- assets: MOCK_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- };
-
- const invalidInputs = [
- { ...validInput, assets: "" },
- { ...validInput, assets: "1,000" },
- { ...validInput, assets: "1.2.3" },
- { ...validInput, assets: "abc" },
- ];
-
- invalidInputs.forEach(input => {
- const result = action.argsSchema.safeParse(input);
- expect(result.success).toBe(false);
- });
- });
-});
-
-describe("Morpho Withdraw Action", () => {
- const NETWORK_ID = Coinbase.networks.BaseSepolia;
- const TRANSACTION_HASH = "0xabcdef1234567890";
- const TRANSACTION_LINK = `https://etherscan.io/tx/${TRANSACTION_HASH}`;
-
- const action = new MorphoWithdrawAction();
-
- let mockContractInvocation: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockContractInvocation = {
- wait: jest.fn().mockResolvedValue({
- getTransaction: jest.fn().mockReturnValue({
- getTransactionHash: jest.fn().mockReturnValue(TRANSACTION_HASH),
- getTransactionLink: jest.fn().mockReturnValue(TRANSACTION_LINK),
- }),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet = {
- invokeContract: jest.fn(),
- getDefaultAddress: jest.fn().mockResolvedValue({
- getId: jest.fn().mockReturnValue(MOCK_RECEIVER_ID),
- }),
- getNetworkId: jest.fn().mockReturnValue(NETWORK_ID),
- } as unknown as jest.Mocked;
-
- mockWallet.invokeContract.mockResolvedValue(mockContractInvocation);
- });
-
- it("should successfully withdraw from Morpho Vault", async () => {
- const args = {
- vaultAddress: MOCK_VAULT_ADDRESS,
- assets: MOCK_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- };
-
- const response = await action.func(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalledWith({
- contractAddress: MOCK_VAULT_ADDRESS,
- method: "withdraw",
- abi: METAMORPHO_ABI,
- args: {
- assets: MOCK_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- owner: MOCK_RECEIVER_ID,
- },
- });
- expect(mockContractInvocation.wait).toHaveBeenCalled();
- expect(response).toContain(`Withdrawn ${MOCK_ASSETS}`);
- expect(response).toContain(`from Morpho Vault ${MOCK_VAULT_ADDRESS}`);
- expect(response).toContain(`with transaction hash: ${TRANSACTION_HASH}`);
- expect(response).toContain(`and transaction link: ${TRANSACTION_LINK}`);
- });
-
- it("should handle errors when withdrawing", async () => {
- const args = {
- vaultAddress: MOCK_VAULT_ADDRESS,
- assets: MOCK_ASSETS,
- receiver: MOCK_RECEIVER_ID,
- };
-
- const error = new Error("API Error");
- mockWallet.invokeContract.mockRejectedValue(error);
-
- const response = await action.func(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalled();
- expect(response).toContain(`Error withdrawing from Morpho Vault: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/defi_wow_buy_token_test.ts b/cdp-agentkit-core/typescript/src/tests/defi_wow_buy_token_test.ts
deleted file mode 100644
index 9b6b198dc..000000000
--- a/cdp-agentkit-core/typescript/src/tests/defi_wow_buy_token_test.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-import { Coinbase, ContractInvocation, Wallet } from "@coinbase/coinbase-sdk";
-
-import { WOW_ABI } from "../actions/cdp/defi/wow/constants";
-import { wowBuyToken, WowBuyTokenInput } from "../actions/cdp/defi/wow/actions/buy_token";
-import { getBuyQuote } from "../actions/cdp/defi/wow/utils";
-import { getHasGraduated } from "../actions/cdp/defi/wow/uniswap/utils";
-
-jest.mock("../actions/cdp/defi/wow/utils", () => ({
- getBuyQuote: jest.fn(),
-}));
-
-jest.mock("../actions/cdp/defi/wow/uniswap/utils", () => ({
- getHasGraduated: jest.fn(),
-}));
-
-const MOCK_CONTRACT_ADDRESS = "0xabcdef123456789";
-const MOCK_AMOUNT_ETH_IN_WEI = "100000000000000000";
-
-describe("Wow Buy Token Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- amountEthInWei: MOCK_AMOUNT_ETH_IN_WEI,
- };
-
- const result = WowBuyTokenInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = WowBuyTokenInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Wow Buy Token Action", () => {
- const NETWORK_ID = Coinbase.networks.BaseSepolia;
- const TRANSACTION_HASH = "0xghijkl987654321";
-
- let mockContractInvocation: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockWallet = {
- invokeContract: jest.fn(),
- getDefaultAddress: jest.fn().mockResolvedValue({
- getId: jest.fn().mockReturnValue(TRANSACTION_HASH),
- }),
- getNetworkId: jest.fn().mockReturnValue(NETWORK_ID),
- } as unknown as jest.Mocked;
-
- mockContractInvocation = {
- wait: jest.fn().mockResolvedValue({
- getTransaction: jest.fn().mockReturnValue({
- getTransactionHash: jest.fn().mockReturnValue(TRANSACTION_HASH),
- }),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet.invokeContract.mockResolvedValue(mockContractInvocation);
- });
-
- it("should successfully buy a token", async () => {
- const args = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- amountEthInWei: MOCK_AMOUNT_ETH_IN_WEI,
- };
-
- (getHasGraduated as jest.Mock).mockResolvedValue(true);
- (getBuyQuote as jest.Mock).mockResolvedValue(1.0);
-
- const response = await wowBuyToken(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalledWith({
- contractAddress: MOCK_CONTRACT_ADDRESS,
- method: "buy",
- abi: WOW_ABI,
- args: {
- recipient: expect.any(String),
- refundRecipient: expect.any(String),
- orderReferrer: "0x0000000000000000000000000000000000000000",
- expectedMarketType: "1",
- minOrderSize: expect.any(String),
- sqrtPriceLimitX96: "0",
- comment: "",
- },
- amount: BigInt(args.amountEthInWei),
- assetId: "wei",
- });
- expect(getBuyQuote).toHaveBeenCalled();
- expect(getHasGraduated).toHaveBeenCalled();
- expect(response).toContain(
- `Purchased WoW ERC20 memecoin with transaction hash: ${TRANSACTION_HASH}`,
- );
- });
-
- it("should handle errors when buying a token", async () => {
- const args = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- amountEthInWei: MOCK_AMOUNT_ETH_IN_WEI,
- };
-
- const error = new Error("An error has occurred");
- mockWallet.invokeContract.mockRejectedValue(error);
- (getHasGraduated as jest.Mock).mockResolvedValue(true);
-
- const response = await wowBuyToken(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalled();
- expect(response).toContain(`Error buying Zora Wow ERC20 memecoin: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/defi_wow_create_token_test.ts b/cdp-agentkit-core/typescript/src/tests/defi_wow_create_token_test.ts
deleted file mode 100644
index 3b2a82b52..000000000
--- a/cdp-agentkit-core/typescript/src/tests/defi_wow_create_token_test.ts
+++ /dev/null
@@ -1,139 +0,0 @@
-import { Coinbase, ContractInvocation, Wallet } from "@coinbase/coinbase-sdk";
-
-import {
- getFactoryAddress,
- GENERIC_TOKEN_METADATA_URI,
- WOW_FACTORY_ABI,
-} from "../actions/cdp/defi/wow/constants";
-import { wowCreateToken, WowCreateTokenInput } from "../actions/cdp/defi/wow/actions/create_token";
-
-jest.mock("../actions/cdp/defi/wow/constants", () => ({
- getFactoryAddress: jest.fn(),
-}));
-
-const MOCK_NAME = "Test Token";
-const MOCK_SYMBOL = "TEST";
-const MOCK_URI = "ipfs://QmY1GqprFYvojCcUEKgqHeDj9uhZD9jmYGrQTfA9vAE78J";
-
-describe("Wow Create Token Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- name: MOCK_NAME,
- symbol: MOCK_SYMBOL,
- tokenUri: MOCK_URI,
- };
-
- const result = WowCreateTokenInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should successfully parse input without tokenUri", () => {
- const validInput = {
- name: MOCK_NAME,
- symbol: MOCK_SYMBOL,
- };
-
- const result = WowCreateTokenInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail with missing required fields", () => {
- const invalidInput = {
- symbol: MOCK_SYMBOL,
- };
- const result = WowCreateTokenInput.safeParse(invalidInput);
-
- expect(result.success).toBe(false);
- });
-
- it("should fail with invalid tokenUri", () => {
- const invalidInput = {
- name: MOCK_NAME,
- symbol: MOCK_SYMBOL,
- tokenUri: 12345,
- };
- const result = WowCreateTokenInput.safeParse(invalidInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Wow Create Token Action", () => {
- const CONTRACT_ADDRESS = "0xabcdef123456789";
- const NETWORK_ID = Coinbase.networks.BaseSepolia;
- const TRANSACTION_HASH = "0xghijkl987654321";
- const WALLET_ID = "0x123456789abcdef";
-
- let mockContractInvocation: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockWallet = {
- invokeContract: jest.fn(),
- getDefaultAddress: jest.fn().mockResolvedValue({
- getId: jest.fn().mockReturnValue(WALLET_ID),
- }),
- getNetworkId: jest.fn().mockReturnValue(NETWORK_ID),
- } as unknown as jest.Mocked;
-
- mockContractInvocation = {
- wait: jest.fn().mockResolvedValue({
- getTransaction: jest.fn().mockReturnValue({
- getTransactionHash: jest.fn().mockReturnValue(TRANSACTION_HASH),
- }),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet.invokeContract.mockResolvedValue(mockContractInvocation);
- });
-
- it("should successfully create a token", async () => {
- const args = {
- name: MOCK_NAME,
- symbol: MOCK_SYMBOL,
- tokenUri: MOCK_URI,
- };
-
- (getFactoryAddress as jest.Mock).mockReturnValue(CONTRACT_ADDRESS);
-
- const response = await wowCreateToken(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalledWith({
- contractAddress: CONTRACT_ADDRESS,
- method: "deploy",
- abi: WOW_FACTORY_ABI,
- args: {
- _tokenCreator: WALLET_ID,
- _platformReferrer: "0x0000000000000000000000000000000000000000",
- _tokenURI: args.tokenUri || GENERIC_TOKEN_METADATA_URI,
- _name: args.name,
- _symbol: args.symbol,
- },
- });
- expect(mockContractInvocation.wait).toHaveBeenCalled();
- expect(response).toContain(`Created WoW ERC20 memecoin ${MOCK_NAME}`);
- expect(response).toContain(`with symbol ${MOCK_SYMBOL}`);
- expect(response).toContain(`on network ${NETWORK_ID}`);
- expect(response).toContain(`Transaction hash for the token creation: ${TRANSACTION_HASH}`);
- });
-
- it("should handle errors when creating a token", async () => {
- const args = {
- name: MOCK_NAME,
- symbol: MOCK_SYMBOL,
- tokenUri: MOCK_URI,
- };
-
- const error = new Error("An error has occurred");
- mockWallet.invokeContract.mockRejectedValue(error);
-
- const response = await wowCreateToken(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalled();
- expect(response).toContain(`Error creating Zora Wow ERC20 memecoin: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/defi_wow_sell_token_test.ts b/cdp-agentkit-core/typescript/src/tests/defi_wow_sell_token_test.ts
deleted file mode 100644
index e918ec7e6..000000000
--- a/cdp-agentkit-core/typescript/src/tests/defi_wow_sell_token_test.ts
+++ /dev/null
@@ -1,137 +0,0 @@
-import { Coinbase, ContractInvocation, Wallet } from "@coinbase/coinbase-sdk";
-
-import { WOW_ABI } from "../actions/cdp/defi/wow/constants";
-import { wowSellToken, WowSellTokenInput } from "../actions/cdp/defi/wow/actions/sell_token";
-import { getSellQuote } from "../actions/cdp/defi/wow/utils";
-import { getHasGraduated } from "../actions/cdp/defi/wow/uniswap/utils";
-
-jest.mock("../actions/cdp/defi/wow/utils", () => ({
- getSellQuote: jest.fn(),
-}));
-
-jest.mock("../actions/cdp/defi/wow/uniswap/utils", () => ({
- getHasGraduated: jest.fn(),
-}));
-
-const MOCK_CONTRACT_ADDRESS = "0x036cbd53842c5426634e7929541ec2318f3dcf7e";
-const MOCK_AMOUNT_TOKENS_IN_WEI = "1000000000000000000";
-
-describe("Wow Sell Token Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- amountTokensInWei: MOCK_AMOUNT_TOKENS_IN_WEI,
- };
-
- const result = WowSellTokenInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail with missing amountTokensInWei", () => {
- const invalidInput = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- };
- const result = WowSellTokenInput.safeParse(invalidInput);
-
- expect(result.success).toBe(false);
- });
-
- it("does not fail with invalid contract address", () => {
- const invalidInput = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- amountTokensInWei: MOCK_AMOUNT_TOKENS_IN_WEI,
- };
- const result = WowSellTokenInput.safeParse(invalidInput);
-
- expect(result.success).toBe(true);
- });
-
- it("does not fail with non-numeric amountTokensInWei", () => {
- const invalidInput = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- amountTokensInWei: "not_a_number",
- };
- const result = WowSellTokenInput.safeParse(invalidInput);
-
- expect(result.success).toBe(true);
- });
-});
-
-describe("Wow Sell Token Action", () => {
- const ADDRESS_ID = "0xabcdef123456789";
- const NETWORK_ID = Coinbase.networks.BaseSepolia;
- const TRANSACTION_HASH = "0xghijkl987654321";
-
- let mockContractInvocation: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockWallet = {
- invokeContract: jest.fn(),
- getNetworkId: jest.fn().mockReturnValue(NETWORK_ID),
- getDefaultAddress: jest.fn().mockResolvedValue({
- getId: jest.fn().mockReturnValue(ADDRESS_ID),
- }),
- } as unknown as jest.Mocked;
-
- mockContractInvocation = {
- wait: jest.fn().mockResolvedValue({
- getTransaction: jest.fn().mockReturnValue({
- getTransactionHash: jest.fn().mockReturnValue(TRANSACTION_HASH),
- }),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet.invokeContract.mockResolvedValue(mockContractInvocation);
- });
-
- it("should successfully sell tokens", async () => {
- const args = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- amountTokensInWei: MOCK_AMOUNT_TOKENS_IN_WEI,
- };
-
- (getHasGraduated as jest.Mock).mockResolvedValue(true);
- (getSellQuote as jest.Mock).mockResolvedValue(1.0);
-
- const response = await wowSellToken(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalledWith({
- contractAddress: MOCK_CONTRACT_ADDRESS,
- method: "sell",
- abi: WOW_ABI,
- args: {
- tokensToSell: MOCK_AMOUNT_TOKENS_IN_WEI,
- recipient: expect.any(String),
- orderReferrer: "0x0000000000000000000000000000000000000000",
- comment: "",
- expectedMarketType: "1",
- minPayoutSize: expect.any(String),
- sqrtPriceLimitX96: "0",
- },
- });
- expect(getSellQuote).toHaveBeenCalled();
- expect(getHasGraduated).toHaveBeenCalled();
- expect(response).toContain(
- `Sold WoW ERC20 memecoin with transaction hash: ${TRANSACTION_HASH}`,
- );
- });
-
- it("should handle errors when selling tokens", async () => {
- const args = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- amountTokensInWei: MOCK_AMOUNT_TOKENS_IN_WEI,
- };
-
- const error = new Error("An error has occurred");
- mockWallet.invokeContract.mockRejectedValue(error);
- (getHasGraduated as jest.Mock).mockResolvedValue(true);
-
- const response = await wowSellToken(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalled();
- expect(response).toContain(`Error selling Zora Wow ERC20 memecoin: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/deploy_contract_test.ts b/cdp-agentkit-core/typescript/src/tests/deploy_contract_test.ts
deleted file mode 100644
index 901970c01..000000000
--- a/cdp-agentkit-core/typescript/src/tests/deploy_contract_test.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-import { SmartContract, Wallet } from "@coinbase/coinbase-sdk";
-
-import { deployContract, DeployContractInput } from "../actions/cdp/deploy_contract";
-
-const MOCK_CONTRACT_NAME = "Test Contract";
-const MOCK_SOLIDITY_VERSION = "0.8.0";
-const MOCK_SOLIDITY_INPUT_JSON = "{}";
-const MOCK_CONSTRUCTOR_ARGS = { arg1: "value1", arg2: "value2" };
-
-describe("Deploy Contract Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- solidityVersion: MOCK_SOLIDITY_VERSION,
- solidityInputJson: MOCK_SOLIDITY_INPUT_JSON,
- contractName: MOCK_CONTRACT_NAME,
- constructorArgs: MOCK_CONSTRUCTOR_ARGS,
- };
-
- const result = DeployContractInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = DeployContractInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Deploy Contract Action", () => {
- const CONTRACT_ADDRESS = "0x123456789abcdef";
- const TRANSACTION_HASH = "0xghijkl987654321";
- const TRANSACTION_LINK = `https://etherscan.io/tx/${TRANSACTION_HASH}`;
-
- let mockSmartContract: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockSmartContract = {
- wait: jest.fn().mockResolvedValue({
- getContractAddress: jest.fn().mockReturnValue(CONTRACT_ADDRESS),
- getTransaction: jest.fn().mockReturnValue({
- getTransactionLink: jest.fn().mockReturnValue(TRANSACTION_LINK),
- }),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet = {
- deployContract: jest.fn(),
- } as unknown as jest.Mocked;
-
- mockWallet.deployContract.mockResolvedValue(mockSmartContract);
- });
-
- it("should successfully respond", async () => {
- const args = {
- solidityVersion: MOCK_SOLIDITY_VERSION,
- solidityInputJson: MOCK_SOLIDITY_INPUT_JSON,
- contractName: MOCK_CONTRACT_NAME,
- constructorArgs: MOCK_CONSTRUCTOR_ARGS,
- };
-
- const response = await deployContract(mockWallet, args);
-
- expect(mockWallet.deployContract).toHaveBeenCalledWith({
- solidityVersion: "0.8.0+commit.c7dfd78e",
- solidityInputJson: MOCK_SOLIDITY_INPUT_JSON,
- contractName: MOCK_CONTRACT_NAME,
- constructorArgs: MOCK_CONSTRUCTOR_ARGS,
- });
- expect(mockSmartContract.wait).toHaveBeenCalled();
- expect(response).toContain(
- `Deployed contract ${MOCK_CONTRACT_NAME} at address ${CONTRACT_ADDRESS}`,
- );
- expect(response).toContain(`Transaction link: ${TRANSACTION_LINK}`);
- });
-
- it("should fail with an error", async () => {
- const args = {
- solidityVersion: MOCK_SOLIDITY_VERSION,
- solidityInputJson: MOCK_SOLIDITY_INPUT_JSON,
- contractName: MOCK_CONTRACT_NAME,
- constructorArgs: MOCK_CONSTRUCTOR_ARGS,
- };
-
- const error = new Error("An error has occurred");
- mockWallet.deployContract.mockRejectedValue(error);
-
- const response = await deployContract(mockWallet, args);
-
- expect(mockWallet.deployContract).toHaveBeenCalledWith({
- solidityVersion: "0.8.0+commit.c7dfd78e",
- solidityInputJson: MOCK_SOLIDITY_INPUT_JSON,
- contractName: MOCK_CONTRACT_NAME,
- constructorArgs: MOCK_CONSTRUCTOR_ARGS,
- });
- expect(response).toContain(`Error deploying contract: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/deploy_nft_test.ts b/cdp-agentkit-core/typescript/src/tests/deploy_nft_test.ts
deleted file mode 100644
index 480d36f89..000000000
--- a/cdp-agentkit-core/typescript/src/tests/deploy_nft_test.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-import { Coinbase, SmartContract, Wallet } from "@coinbase/coinbase-sdk";
-
-import { deployNft, DeployNftInput } from "../actions/cdp/deploy_nft";
-
-const MOCK_NFT_BASE_URI = "https://www.test.xyz/metadata/";
-const MOCK_NFT_NAME = "Test Token";
-const MOCK_NFT_SYMBOL = "TEST";
-
-describe("Deploy NFT Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- baseURI: MOCK_NFT_BASE_URI,
- name: MOCK_NFT_NAME,
- symbol: MOCK_NFT_SYMBOL,
- };
-
- const result = DeployNftInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("sould fail parsing empty input", () => {
- const emptyInput = {};
- const result = DeployNftInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Deploy NFT Action", () => {
- const CONTRACT_ADDRESS = "0x123456789abcdef";
- const NETWORK_ID = Coinbase.networks.BaseSepolia;
- const TRANSACTION_HASH = "0xghijkl987654321";
- const TRANSACTION_LINK = `https://etherscan.io/tx/${TRANSACTION_HASH}`;
-
- let mockSmartContract: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockSmartContract = {
- wait: jest.fn().mockResolvedValue({
- getContractAddress: jest.fn().mockReturnValue(CONTRACT_ADDRESS),
- getTransaction: jest.fn().mockReturnValue({
- getTransactionHash: jest.fn().mockReturnValue(TRANSACTION_HASH),
- getTransactionLink: jest.fn().mockReturnValue(TRANSACTION_LINK),
- }),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet = {
- deployNFT: jest.fn(),
- getNetworkId: jest.fn().mockReturnValue(NETWORK_ID),
- } as unknown as jest.Mocked;
-
- mockWallet.deployNFT.mockResolvedValue(mockSmartContract);
- });
-
- it("should successfully respond", async () => {
- const args = {
- name: MOCK_NFT_NAME,
- symbol: MOCK_NFT_SYMBOL,
- baseURI: MOCK_NFT_BASE_URI,
- };
-
- const response = await deployNft(mockWallet, args);
-
- expect(mockWallet.deployNFT).toHaveBeenCalledWith(args);
- expect(mockSmartContract.wait).toHaveBeenCalled();
- expect(response).toContain(`Deployed NFT Collection ${MOCK_NFT_NAME}`);
- expect(response).toContain(`to address ${CONTRACT_ADDRESS}`);
- expect(response).toContain(`on network ${NETWORK_ID}`);
- expect(response).toContain(`Transaction hash for the deployment: ${TRANSACTION_HASH}`);
- expect(response).toContain(`Transaction link for the deployment: ${TRANSACTION_LINK}`);
- });
-
- it("should fail with an error", async () => {
- const args = {
- baseURI: MOCK_NFT_BASE_URI,
- name: MOCK_NFT_NAME,
- symbol: MOCK_NFT_SYMBOL,
- };
-
- const error = new Error("An error has occurred");
- mockWallet.deployNFT.mockRejectedValue(error);
-
- const response = await deployNft(mockWallet, args);
-
- expect(mockWallet.deployNFT).toHaveBeenCalledWith(args);
- expect(response).toContain(`Error deploying NFT: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/deploy_token_test.ts b/cdp-agentkit-core/typescript/src/tests/deploy_token_test.ts
deleted file mode 100644
index e0dc150e8..000000000
--- a/cdp-agentkit-core/typescript/src/tests/deploy_token_test.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-import { SmartContract, Wallet } from "@coinbase/coinbase-sdk";
-
-import { deployToken, DeployTokenInput } from "../actions/cdp/deploy_token";
-
-const MOCK_TOKEN_NAME = "Test Token";
-const MOCK_TOKEN_SYMBOL = "TEST";
-const MOCK_TOKEN_SUPPLY = 100;
-
-describe("Deploy Token Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- name: MOCK_TOKEN_NAME,
- symbol: MOCK_TOKEN_SYMBOL,
- totalSupply: MOCK_TOKEN_SUPPLY,
- };
-
- const result = DeployTokenInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = DeployTokenInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Deploy Token Action", () => {
- const CONTRACT_ADDRESS = "0x123456789abcdef";
- const TRANSACTION_HASH = "0xghijkl987654321";
- const TRANSACTION_LINK = `https://etherscan.io/tx/${TRANSACTION_HASH}`;
-
- let mockSmartContract: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockSmartContract = {
- wait: jest.fn().mockResolvedValue({
- getContractAddress: jest.fn().mockReturnValue(CONTRACT_ADDRESS),
- getTransaction: jest.fn().mockReturnValue({
- getTransactionLink: jest.fn().mockReturnValue(TRANSACTION_LINK),
- }),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet = {
- deployToken: jest.fn(),
- } as unknown as jest.Mocked;
-
- mockWallet.deployToken.mockResolvedValue(mockSmartContract);
- });
-
- it("should successfully respond", async () => {
- const args = {
- name: MOCK_TOKEN_NAME,
- symbol: MOCK_TOKEN_SYMBOL,
- totalSupply: MOCK_TOKEN_SUPPLY,
- };
-
- const response = await deployToken(mockWallet, args);
-
- expect(mockWallet.deployToken).toHaveBeenCalledWith(args);
- expect(mockSmartContract.wait).toHaveBeenCalled();
- expect(response).toContain(
- `Deployed ERC20 token contract ${MOCK_TOKEN_NAME} (${MOCK_TOKEN_SYMBOL})`,
- );
- expect(response).toContain(`with total supply of ${MOCK_TOKEN_SUPPLY}`);
- expect(response).toContain(`tokens at address ${CONTRACT_ADDRESS}`);
- expect(response).toContain(`Transaction link: ${TRANSACTION_LINK}`);
- });
-
- it("should fail with an error", async () => {
- const args = {
- name: MOCK_TOKEN_NAME,
- symbol: MOCK_TOKEN_SYMBOL,
- totalSupply: MOCK_TOKEN_SUPPLY,
- };
-
- const error = new Error("An error has occurred");
- mockWallet.deployToken.mockRejectedValue(error);
-
- const response = await deployToken(mockWallet, args);
-
- expect(mockWallet.deployToken).toHaveBeenCalledWith(args);
- expect(response).toContain(`Error deploying token: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/get_balance_nft_test.ts b/cdp-agentkit-core/typescript/src/tests/get_balance_nft_test.ts
deleted file mode 100644
index 29412050f..000000000
--- a/cdp-agentkit-core/typescript/src/tests/get_balance_nft_test.ts
+++ /dev/null
@@ -1,129 +0,0 @@
-import { GetBalanceNftInput, getBalanceNft } from "../actions/cdp/get_balance_nft";
-import { Wallet } from "@coinbase/coinbase-sdk";
-import { readContract } from "@coinbase/coinbase-sdk";
-
-const MOCK_CONTRACT_ADDRESS = "0xvalidContractAddress";
-const MOCK_ADDRESS = "0xvalidAddress";
-const MOCK_TOKEN_IDS = ["1", "2", "3"];
-
-jest.mock("@coinbase/coinbase-sdk", () => ({
- ...jest.requireActual("@coinbase/coinbase-sdk"),
- readContract: jest.fn(),
-}));
-
-describe("GetBalanceNft", () => {
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockWallet = {
- getDefaultAddress: jest.fn().mockResolvedValue({ getId: () => MOCK_ADDRESS }),
- getNetworkId: jest.fn().mockReturnValue("base-sepolia"),
- } as unknown as jest.Mocked;
-
- (readContract as jest.Mock).mockClear();
- });
-
- it("should validate input schema with all parameters", () => {
- const input = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- address: MOCK_ADDRESS,
- };
-
- const result = GetBalanceNftInput.safeParse(input);
- expect(result.success).toBe(true);
- });
-
- it("should validate input schema with required parameters only", () => {
- const input = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- };
-
- const result = GetBalanceNftInput.safeParse(input);
- expect(result.success).toBe(true);
- });
-
- it("should fail validation with missing required parameters", () => {
- const input = {};
-
- const result = GetBalanceNftInput.safeParse(input);
- expect(result.success).toBe(false);
- });
-
- it("should successfully get NFT balance using default address", async () => {
- (readContract as jest.Mock).mockResolvedValueOnce(MOCK_TOKEN_IDS);
-
- const input = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- };
-
- const response = await getBalanceNft(mockWallet, input);
-
- expect(mockWallet.getDefaultAddress).toHaveBeenCalled();
- expect(readContract).toHaveBeenCalledWith({
- contractAddress: MOCK_CONTRACT_ADDRESS,
- networkId: "base-sepolia",
- method: "tokensOfOwner",
- args: { owner: MOCK_ADDRESS },
- });
-
- expect(response).toBe(
- `Address ${MOCK_ADDRESS} owns ${MOCK_TOKEN_IDS.length} NFTs in contract ${MOCK_CONTRACT_ADDRESS}.\n` +
- `Token IDs: ${MOCK_TOKEN_IDS.join(", ")}`,
- );
- });
-
- it("should handle case when no tokens are owned", async () => {
- (readContract as jest.Mock).mockResolvedValueOnce([]);
-
- const input = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- address: MOCK_ADDRESS,
- };
-
- const response = await getBalanceNft(mockWallet, input);
-
- expect(response).toBe(
- `Address ${MOCK_ADDRESS} owns no NFTs in contract ${MOCK_CONTRACT_ADDRESS}`,
- );
- });
-
- it("should get NFT balance with specific address", async () => {
- const customAddress = "0xcustomAddress";
- (readContract as jest.Mock).mockResolvedValueOnce(MOCK_TOKEN_IDS);
-
- const input = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- address: customAddress,
- };
-
- const response = await getBalanceNft(mockWallet, input);
-
- expect(readContract).toHaveBeenCalledWith({
- contractAddress: MOCK_CONTRACT_ADDRESS,
- networkId: "base-sepolia",
- method: "tokensOfOwner",
- args: { owner: customAddress },
- });
-
- expect(response).toBe(
- `Address ${customAddress} owns ${MOCK_TOKEN_IDS.length} NFTs in contract ${MOCK_CONTRACT_ADDRESS}.\n` +
- `Token IDs: ${MOCK_TOKEN_IDS.join(", ")}`,
- );
- });
-
- it("should handle API errors gracefully", async () => {
- const errorMessage = "API error";
- (readContract as jest.Mock).mockRejectedValueOnce(new Error(errorMessage));
-
- const input = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- address: MOCK_ADDRESS,
- };
-
- const response = await getBalanceNft(mockWallet, input);
-
- expect(response).toBe(
- `Error getting NFT balance for address ${MOCK_ADDRESS} in contract ${MOCK_CONTRACT_ADDRESS}: Error: ${errorMessage}`,
- );
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/get_balance_test.ts b/cdp-agentkit-core/typescript/src/tests/get_balance_test.ts
deleted file mode 100644
index 2ff39553b..000000000
--- a/cdp-agentkit-core/typescript/src/tests/get_balance_test.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import { Wallet, WalletAddress } from "@coinbase/coinbase-sdk";
-import { getBalance, GetBalanceInput } from "../actions/cdp/get_balance";
-
-const MOCK_ASSET_ID = "test-asset-id";
-const MOCK_BALANCE = 1000000000000000000;
-
-describe("Get Balance Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- assetId: MOCK_ASSET_ID,
- };
-
- const result = GetBalanceInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = GetBalanceInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Get Balance Action", () => {
- const WALLET_ID = "0x123456789abcdef";
-
- let mockAddresses: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockAddresses = [
- {
- getId: jest.fn().mockReturnValue("test-address-id-1"),
- getBalance: jest.fn().mockReturnValue(MOCK_BALANCE),
- } as unknown as jest.Mocked,
- {
- getId: jest.fn().mockReturnValue("test-address-id-2"),
- getBalance: jest.fn().mockReturnValue(0.0),
- } as unknown as jest.Mocked,
- {
- getId: jest.fn().mockReturnValue("test-address-id-3"),
- getBalance: jest.fn().mockReturnValue(MOCK_BALANCE),
- } as unknown as jest.Mocked,
- ] as unknown as jest.Mocked[];
-
- mockWallet = {
- getId: jest.fn().mockReturnValue(WALLET_ID),
- listAddresses: jest.fn(),
- } as unknown as jest.Mocked;
-
- mockWallet.listAddresses.mockResolvedValue(mockAddresses);
- });
-
- it("should successfully respond", async () => {
- const args = {
- assetId: MOCK_ASSET_ID,
- };
-
- const response = await getBalance(mockWallet, args);
-
- expect(mockWallet.listAddresses).toHaveBeenCalledWith();
- mockAddresses.forEach(address => {
- expect(address.getBalance).toHaveBeenCalledWith(MOCK_ASSET_ID);
- expect(response).toContain(`${address.getId()}: ${address.getBalance(MOCK_ASSET_ID)}`);
- });
- expect(response).toContain(`Balances for wallet ${WALLET_ID}`);
- });
-
- it("should fail with an error", async () => {
- const args = {
- assetId: MOCK_ASSET_ID,
- };
-
- const error = new Error("An error has occurred");
- mockWallet.listAddresses.mockRejectedValue(error);
-
- const response = await getBalance(mockWallet, args);
-
- expect(mockWallet.listAddresses).toHaveBeenCalled();
- expect(response).toContain(`Error getting balance for all addresses in the wallet: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/get_wallet_details_test.ts b/cdp-agentkit-core/typescript/src/tests/get_wallet_details_test.ts
deleted file mode 100644
index d6b096612..000000000
--- a/cdp-agentkit-core/typescript/src/tests/get_wallet_details_test.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import { Coinbase, Wallet, WalletAddress } from "@coinbase/coinbase-sdk";
-
-import { getWalletDetails, GetWalletDetailsInput } from "../actions/cdp/get_wallet_details";
-
-describe("Wallet Details Input", () => {
- it("should successfully parse empty input", () => {
- const emptyInput = {};
- const result = GetWalletDetailsInput.safeParse(emptyInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(emptyInput);
- });
-});
-
-describe("Wallet Details Action", () => {
- const ADDRESS_ID = "0xabcdef123456789";
- const NETWORK_ID = Coinbase.networks.BaseSepolia;
- const WALLET_ID = "0x123456789abcdef";
-
- let mockAddress: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockAddress = {
- getId: jest.fn().mockReturnValue(ADDRESS_ID),
- } as unknown as jest.Mocked;
-
- mockWallet = {
- getDefaultAddress: jest.fn(),
- getId: jest.fn().mockReturnValue(WALLET_ID),
- getNetworkId: jest.fn().mockReturnValue(NETWORK_ID),
- } as unknown as jest.Mocked;
-
- mockWallet.getDefaultAddress.mockResolvedValue(mockAddress);
- });
-
- it("should successfully respond", async () => {
- const args = {};
- const response = await getWalletDetails(mockWallet, args);
-
- expect(mockWallet.getDefaultAddress).toHaveBeenCalled();
- expect(response).toContain(`Wallet: ${WALLET_ID}`);
- expect(response).toContain(`on network: ${NETWORK_ID}`);
- expect(response).toContain(`with default address: ${ADDRESS_ID}`);
- });
-
- it("should fail with an error", async () => {
- const args = {};
-
- const error = new Error("An error has occurred");
- mockWallet.getDefaultAddress.mockRejectedValue(error);
-
- const response = await getWalletDetails(mockWallet, args);
-
- expect(mockWallet.getDefaultAddress).toHaveBeenCalled();
- expect(response).toContain(`Error getting wallet details: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/mint_nft_test.ts b/cdp-agentkit-core/typescript/src/tests/mint_nft_test.ts
deleted file mode 100644
index f151ad609..000000000
--- a/cdp-agentkit-core/typescript/src/tests/mint_nft_test.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { Coinbase, ContractInvocation, Wallet } from "@coinbase/coinbase-sdk";
-
-import { mintNft, MintNftInput } from "../actions/cdp/mint_nft";
-
-const MOCK_CONTRACT_ADDRESS = "0x123456789abcdef";
-const MOCK_CONTRACT_DESTINATION = "0xabcdef123456789";
-
-describe("Mint NFT Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- destination: MOCK_CONTRACT_DESTINATION,
- };
-
- const result = MintNftInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = MintNftInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Mint NFT Action", () => {
- const NETWORK_ID = Coinbase.networks.BaseSepolia;
- const TRANSACTION_HASH = "0xghijkl987654321";
- const TRANSACTION_LINK = `https://etherscan.io/tx/${TRANSACTION_HASH}`;
-
- let mockContractInvocation: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockContractInvocation = {
- wait: jest.fn().mockResolvedValue({
- getTransaction: jest.fn().mockReturnValue({
- getTransactionHash: jest.fn().mockReturnValue(TRANSACTION_HASH),
- getTransactionLink: jest.fn().mockReturnValue(TRANSACTION_LINK),
- }),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet = {
- invokeContract: jest.fn(),
- getNetworkId: jest.fn().mockReturnValue(NETWORK_ID),
- } as unknown as jest.Mocked;
-
- mockWallet.invokeContract.mockResolvedValue(mockContractInvocation);
- });
-
- it("should successfully respond", async () => {
- const args = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- destination: MOCK_CONTRACT_DESTINATION,
- };
-
- const response = await mintNft(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalledWith({
- contractAddress: MOCK_CONTRACT_ADDRESS,
- method: "mint",
- args: {
- to: MOCK_CONTRACT_DESTINATION,
- quantity: "1",
- },
- });
- expect(mockContractInvocation.wait).toHaveBeenCalled();
- expect(response).toContain(`Minted NFT from contract ${MOCK_CONTRACT_ADDRESS}`);
- expect(response).toContain(`to address ${MOCK_CONTRACT_DESTINATION}`);
- expect(response).toContain(`on network ${NETWORK_ID}`);
- expect(response).toContain(`Transaction hash for the mint: ${TRANSACTION_HASH}`);
- expect(response).toContain(`Transaction link for the mint: ${TRANSACTION_LINK}`);
- });
-
- it("should fail with an error", async () => {
- const args = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- destination: MOCK_CONTRACT_DESTINATION,
- };
-
- const error = new Error("An error has occurred");
- mockWallet.invokeContract.mockRejectedValue(error);
-
- const response = await mintNft(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalled();
- expect(response).toContain(`Error minting NFT: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/register_basename_test.ts b/cdp-agentkit-core/typescript/src/tests/register_basename_test.ts
deleted file mode 100644
index 138d33334..000000000
--- a/cdp-agentkit-core/typescript/src/tests/register_basename_test.ts
+++ /dev/null
@@ -1,176 +0,0 @@
-import { Coinbase, ContractInvocation, Wallet } from "@coinbase/coinbase-sdk";
-
-import { Decimal } from "decimal.js";
-import { encodeFunctionData, namehash } from "viem";
-
-import {
- registerBasename,
- RegisterBasenameInput,
- BASENAMES_REGISTRAR_CONTROLLER_ADDRESS_MAINNET,
- BASENAMES_REGISTRAR_CONTROLLER_ADDRESS_TESTNET,
- L2_RESOLVER_ABI,
- L2_RESOLVER_ADDRESS_MAINNET,
- L2_RESOLVER_ADDRESS_TESTNET,
- REGISTRATION_DURATION,
- REGISTRAR_ABI,
-} from "../actions/cdp/register_basename";
-
-const MOCK_AMOUNT = "0.123";
-const MOCK_BASENAME = "test-basename";
-
-describe("Register Basename Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- amount: MOCK_AMOUNT,
- basename: MOCK_BASENAME,
- };
-
- const result = RegisterBasenameInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = RegisterBasenameInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Register Basename Action", () => {
- /**
- * This is the default network.
- */
- const NETWORK_ID = Coinbase.networks.BaseMainnet;
-
- /**
- * This is a 40 character hexadecimal string that requires lowercase alpha characters.
- */
- const ADDRESS_ID = "0xe6b2af36b3bb8d47206a129ff11d5a2de2a63c83";
-
- let mockContractInvocation: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockContractInvocation = {
- wait: jest.fn().mockResolvedValue({}),
- } as unknown as jest.Mocked;
-
- mockWallet = {
- getDefaultAddress: jest.fn().mockResolvedValue({
- getId: jest.fn().mockReturnValue(ADDRESS_ID),
- }),
- getNetworkId: jest.fn().mockReturnValue(NETWORK_ID),
- invokeContract: jest.fn(),
- } as unknown as jest.Mocked;
-
- mockWallet.invokeContract.mockResolvedValue(mockContractInvocation);
- });
-
- it(`should Successfully respond with ${MOCK_BASENAME}.base.eth for network: ${Coinbase.networks.BaseMainnet}`, async () => {
- const args = {
- amount: MOCK_AMOUNT,
- basename: MOCK_BASENAME,
- };
-
- const name = `${MOCK_BASENAME}.base.eth`;
-
- mockWallet.getNetworkId.mockReturnValue(Coinbase.networks.BaseMainnet);
-
- const response = await registerBasename(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalledWith({
- contractAddress: BASENAMES_REGISTRAR_CONTROLLER_ADDRESS_MAINNET,
- method: "register",
- args: {
- request: [
- MOCK_BASENAME,
- ADDRESS_ID,
- REGISTRATION_DURATION,
- L2_RESOLVER_ADDRESS_MAINNET,
- [
- encodeFunctionData({
- abi: L2_RESOLVER_ABI,
- functionName: "setAddr",
- args: [namehash(name), ADDRESS_ID],
- }),
- encodeFunctionData({
- abi: L2_RESOLVER_ABI,
- functionName: "setName",
- args: [namehash(name), name],
- }),
- ],
- true,
- ],
- },
- abi: REGISTRAR_ABI,
- amount: new Decimal(MOCK_AMOUNT),
- assetId: "eth",
- });
- expect(mockContractInvocation.wait).toHaveBeenCalled();
- expect(response).toContain(`Successfully registered basename ${MOCK_BASENAME}.base.eth`);
- expect(response).toContain(`for address ${ADDRESS_ID}`);
- });
-
- it(`should Successfully respond with ${MOCK_BASENAME}.basetest.eth for any other network`, async () => {
- const args = {
- amount: MOCK_AMOUNT,
- basename: MOCK_BASENAME,
- };
-
- const name = `${MOCK_BASENAME}.basetest.eth`;
-
- mockWallet.getNetworkId.mockReturnValue("anything-else");
-
- const response = await registerBasename(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalledWith({
- contractAddress: BASENAMES_REGISTRAR_CONTROLLER_ADDRESS_TESTNET,
- method: "register",
- args: {
- request: [
- MOCK_BASENAME,
- ADDRESS_ID,
- REGISTRATION_DURATION,
- L2_RESOLVER_ADDRESS_TESTNET,
- [
- encodeFunctionData({
- abi: L2_RESOLVER_ABI,
- functionName: "setAddr",
- args: [namehash(name), ADDRESS_ID],
- }),
- encodeFunctionData({
- abi: L2_RESOLVER_ABI,
- functionName: "setName",
- args: [namehash(name), name],
- }),
- ],
- true,
- ],
- },
- abi: REGISTRAR_ABI,
- amount: new Decimal(MOCK_AMOUNT),
- assetId: "eth",
- });
- expect(mockContractInvocation.wait).toHaveBeenCalled();
- expect(response).toContain(`Successfully registered basename ${MOCK_BASENAME}.basetest.eth`);
- expect(response).toContain(`for address ${ADDRESS_ID}`);
- });
-
- it("should fail with an error", async () => {
- const args = {
- amount: MOCK_AMOUNT,
- basename: MOCK_BASENAME,
- };
-
- const error = new Error("Failed to register basename");
- mockWallet.invokeContract.mockRejectedValue(error);
-
- await registerBasename(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalled();
- expect(`Error registering basename: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/request_faucet_funds_test.ts b/cdp-agentkit-core/typescript/src/tests/request_faucet_funds_test.ts
deleted file mode 100644
index 605f01e05..000000000
--- a/cdp-agentkit-core/typescript/src/tests/request_faucet_funds_test.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-import { Coinbase, FaucetTransaction, Wallet } from "@coinbase/coinbase-sdk";
-
-import { requestFaucetFunds, RequestFaucetFundsInput } from "../actions/cdp/request_faucet_funds";
-
-const MOCK_ASSET_ID = Coinbase.assets.Usdc;
-
-describe("Request Faucet Funds Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- assetId: MOCK_ASSET_ID,
- };
-
- const result = RequestFaucetFundsInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should successfully parsing empty input", () => {
- const emptyInput = {};
- const result = RequestFaucetFundsInput.safeParse(emptyInput);
-
- expect(result.success).toBe(true);
- });
-});
-
-describe("Request Faucet Funds Action", () => {
- const TRANSACTION_HASH = "0xghijkl987654321";
- const TRANSACTION_LINK = `https://etherscan.io/tx/${TRANSACTION_HASH}`;
-
- let mockFaucetTransaction: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockFaucetTransaction = {
- wait: jest.fn().mockResolvedValue({
- getTransactionLink: jest.fn().mockReturnValue(TRANSACTION_LINK),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet = {
- faucet: jest.fn(),
- } as unknown as jest.Mocked;
-
- mockWallet.faucet.mockResolvedValue(mockFaucetTransaction);
- });
-
- it("should successfully request faucet funds", async () => {
- const args = {};
- const response = await requestFaucetFunds(mockWallet, args);
-
- expect(mockWallet.faucet).toHaveBeenCalled();
- expect(mockFaucetTransaction.wait).toHaveBeenCalled();
- expect(response).toContain(`Received ETH from the faucet. Transaction: ${TRANSACTION_LINK}`);
- });
-
- it("should successfully request faucet funds with an asset id", async () => {
- const args = { assetId: MOCK_ASSET_ID };
- const response = await requestFaucetFunds(mockWallet, args);
-
- expect(mockWallet.faucet).toHaveBeenCalledWith(MOCK_ASSET_ID);
- expect(mockFaucetTransaction.wait).toHaveBeenCalled();
- expect(response).toContain(`Received ${MOCK_ASSET_ID} from the faucet`);
- expect(response).toContain(`Transaction: ${TRANSACTION_LINK}`);
- });
-
- it("should fail with an error", async () => {
- const args = { assetId: MOCK_ASSET_ID };
-
- const error = new Error("Failed to request funds");
- mockWallet.faucet.mockRejectedValue(error);
-
- const response = await requestFaucetFunds(mockWallet, args);
-
- expect(mockWallet.faucet).toHaveBeenCalled();
- expect(response).toContain(`Error requesting faucet funds: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/social_farcaster_account_details_test.ts b/cdp-agentkit-core/typescript/src/tests/social_farcaster_account_details_test.ts
deleted file mode 100644
index 07dfb35f6..000000000
--- a/cdp-agentkit-core/typescript/src/tests/social_farcaster_account_details_test.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import {
- accountDetails,
- AccountDetailsInput,
-} from "../actions/cdp/social/farcaster/account_details";
-
-describe("Farcaster Account Details Input", () => {
- it("should successfully parse empty input", () => {
- const emptyInput = {};
- const result = AccountDetailsInput.safeParse(emptyInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(emptyInput);
- });
-});
-
-describe("Farcaster Account Details Action", () => {
- beforeEach(async () => {
- process.env.NEYNAR_API_KEY = "test-key";
- process.env.NEYNAR_MANAGED_SIGNER = "test-managed-signer";
- });
-
- afterEach(() => {
- jest.resetAllMocks();
- process.env.NEYNAR_API_KEY = "";
- process.env.NEYNAR_MANAGED_SIGNER = "";
- });
-
- it("should successfully retrieve Farcaster account details", async () => {
- global.fetch = jest.fn(() =>
- Promise.resolve({
- json: () =>
- Promise.resolve({
- users: [
- {
- object: "user",
- fid: 193,
- username: "derek",
- display_name: "derek",
- },
- ],
- }),
- }),
- ) as jest.Mock;
-
- const args = {};
- const response = await accountDetails(args);
- expect(response).toContain("Successfully retrieved Farcaster account details:");
- });
-
- it("should handle errors when retrieving Farcaster account details", async () => {
- global.fetch = jest.fn(() => Promise.reject(new Error("An error has occurred"))) as jest.Mock;
-
- const args = {};
- const response = await accountDetails(args);
- expect(response).toContain("Error retrieving Farcaster account details:");
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/social_farcaster_post_cast_test.ts b/cdp-agentkit-core/typescript/src/tests/social_farcaster_post_cast_test.ts
deleted file mode 100644
index 6c204d80e..000000000
--- a/cdp-agentkit-core/typescript/src/tests/social_farcaster_post_cast_test.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { postCast, PostCastInput } from "../actions/cdp/social/farcaster/post_cast";
-
-const MOCK_CAST = "Hello from AgentKit, @CoinbaseDev!";
-
-describe("Post Cast Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = { castText: MOCK_CAST };
- const result = PostCastInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail to parse empty input", () => {
- const emptyInput = {};
- const result = PostCastInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- expect(result.error!.issues[0].message).toBe("Required");
- });
-
- it("should fail to parse invalid input: cast is too long", () => {
- const invalidInput = { castText: "A".repeat(281) };
- const result = PostCastInput.safeParse(invalidInput);
-
- expect(result.success).toBe(false);
- expect(result.error!.issues[0].message).toBe("Cast text must be a maximum of 280 characters.");
- });
-});
-
-describe("Post Cast Action", () => {
- beforeEach(async () => {
- process.env.NEYNAR_API_KEY = "test-key";
- process.env.NEYNAR_MANAGED_SIGNER = "test-managed-signer";
- });
-
- afterEach(() => {
- jest.resetAllMocks();
- process.env.NEYNAR_API_KEY = "";
- process.env.NEYNAR_MANAGED_SIGNER = "";
- });
-
- it("should successfully post a cast", async () => {
- global.fetch = jest.fn(() =>
- Promise.resolve({ json: () => Promise.resolve({ hash: "0x123" }) }),
- ) as jest.Mock;
-
- const args = {
- castText: "Hello, world!",
- };
- const response = await postCast(args);
- expect(response).toContain("Successfully posted cast to Farcaster:");
- });
-
- it("should handle errors when posting a cast", async () => {
- global.fetch = jest.fn(() => Promise.reject(new Error("An error has occurred"))) as jest.Mock;
-
- const args = {
- castText: "Hello, world!",
- };
- const response = await postCast(args);
-
- expect(response).toContain("Error posting to Farcaster:");
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/social_twitter_account_details_test.ts b/cdp-agentkit-core/typescript/src/tests/social_twitter_account_details_test.ts
deleted file mode 100644
index ca8ae9c49..000000000
--- a/cdp-agentkit-core/typescript/src/tests/social_twitter_account_details_test.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import { accountDetails, AccountDetailsInput } from "../actions/cdp/social/twitter/account_details";
-import { TwitterApi, TwitterApiv2 } from "twitter-api-v2";
-
-const MOCK_ID = "1853889445319331840";
-const MOCK_NAME = "CDP Agentkit";
-const MOCK_USERNAME = "CDPAgentkit";
-
-describe("Twitter (X) Account Details Input", () => {
- it("should successfully parse empty input", () => {
- const emptyInput = {};
- const result = AccountDetailsInput.safeParse(emptyInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(emptyInput);
- });
-});
-
-describe("Account Details Action", () => {
- const mockResponse = {
- data: {
- id: MOCK_ID,
- name: MOCK_NAME,
- username: MOCK_USERNAME,
- },
- };
-
- let mockApi: jest.Mocked;
- let mockClient: jest.Mocked;
-
- beforeEach(() => {
- mockClient = {
- me: jest.fn().mockResolvedValue(mockResponse),
- } as unknown as jest.Mocked;
-
- mockApi = {
- get v2() {
- return mockClient;
- },
- } as unknown as jest.Mocked;
- });
-
- it("should successfully retrieve account details", async () => {
- const args = {};
- const response = await accountDetails(mockApi, args);
-
- expect(mockApi.v2.me).toHaveBeenCalled();
- expect(response).toContain("Successfully retrieved authenticated user account details");
- expect(response).toContain(JSON.stringify(mockResponse));
- });
-
- it("should handle errors when retrieving account details", async () => {
- const args = {};
-
- const error = new Error("An error has occurred");
- mockApi.v2.me = jest.fn().mockRejectedValue(error);
-
- const response = await accountDetails(mockApi, args);
-
- expect(mockApi.v2.me).toHaveBeenCalled();
- expect(response).toContain("Error retrieving authenticated user account details");
- expect(response).toContain(error.message);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/social_twitter_account_mentions_test.ts b/cdp-agentkit-core/typescript/src/tests/social_twitter_account_mentions_test.ts
deleted file mode 100644
index 6f48c2943..000000000
--- a/cdp-agentkit-core/typescript/src/tests/social_twitter_account_mentions_test.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import {
- accountMentions,
- AccountMentionsInput,
-} from "../actions/cdp/social/twitter/account_mentions";
-import { TwitterApi, TwitterApiv2 } from "twitter-api-v2";
-
-const MOCK_ACCOUNT_ID = "1857479287504584856";
-
-describe("Account Mentions Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = { userId: MOCK_ACCOUNT_ID };
- const result = AccountMentionsInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail to parse empty input", () => {
- const emptyInput = {};
- const result = AccountMentionsInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- expect(result.error!.issues[0].message).toBe("Required");
- });
-
- it("should fail to parse invalid input", () => {
- const invalidInput = { userId: "" };
- const result = AccountMentionsInput.safeParse(invalidInput);
-
- expect(result.success).toBe(false);
- expect(result.error!.issues[0].message).toBe("Account ID is required.");
- });
-});
-
-describe("Account Mentions Action", () => {
- const mockApiResponse = {
- data: [
- {
- id: "0123456789012345678",
- text: "@CDPAgentkit please reply!",
- },
- ],
- };
-
- let mockApi: jest.Mocked;
- let mockClient: jest.Mocked;
-
- beforeEach(() => {
- mockClient = {
- userMentionTimeline: jest.fn().mockResolvedValue(mockApiResponse),
- } as unknown as jest.Mocked;
-
- mockApi = {
- get v2() {
- return mockClient;
- },
- } as unknown as jest.Mocked;
- });
-
- it("should successfully retrieve account mentions", async () => {
- const args = { userId: MOCK_ACCOUNT_ID };
- const response = await accountMentions(mockApi, args);
-
- expect(mockApi.v2.userMentionTimeline).toHaveBeenCalledWith(MOCK_ACCOUNT_ID);
- expect(response).toContain("Successfully retrieved account mentions:");
- expect(response).toContain(JSON.stringify(mockApiResponse));
- });
-
- it("should handle errors when retrieving account mentions", async () => {
- const args = {
- userId: MOCK_ACCOUNT_ID,
- };
-
- const error = new Error("Twitter API error");
- mockClient.userMentionTimeline.mockRejectedValue(error);
-
- const response = await accountMentions(mockApi, args);
-
- expect(mockApi.v2.userMentionTimeline).toHaveBeenCalledWith(MOCK_ACCOUNT_ID);
- expect(response).toContain("Error retrieving authenticated account mentions:");
- expect(response).toContain(error.message);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/social_twitter_post_tweet_reply_test.ts b/cdp-agentkit-core/typescript/src/tests/social_twitter_post_tweet_reply_test.ts
deleted file mode 100644
index 8e6e25176..000000000
--- a/cdp-agentkit-core/typescript/src/tests/social_twitter_post_tweet_reply_test.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-import { postTweet, PostTweetReplyInput } from "../actions/cdp/social/twitter/post_tweet_reply";
-import { TwitterApi, TwitterApiv2 } from "twitter-api-v2";
-
-const MOCK_TWEET_ID = "0123456789012345678";
-const MOCK_TWEET_REPLY = "hello, world, again!";
-
-describe("Post Tweet Reply Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = { tweetId: MOCK_TWEET_ID, tweetReply: MOCK_TWEET_REPLY };
- const result = PostTweetReplyInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail to parse empty input", () => {
- const emptyInput = {};
- const result = PostTweetReplyInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- expect(result.error!.issues[0].message).toBe("Required");
- });
-
- it("should fail to parse invalid input: tweet is too long", () => {
- const invalidInput = { tweetId: MOCK_TWEET_ID, tweetReply: "A".repeat(281) };
- const result = PostTweetReplyInput.safeParse(invalidInput);
-
- expect(result.success).toBe(false);
- expect(result.error!.issues[0].message).toBe(
- "The reply to the tweet which must be a maximum of 280 characters.",
- );
- });
-});
-
-describe("Post Tweet Reply Action", () => {
- const mockApiResponse = {
- data: {
- id: "9123456789012345678",
- edit_history_tweet_ids: ["9123456789012345678"],
- text: MOCK_TWEET_REPLY,
- },
- };
-
- let mockApi: jest.Mocked;
- let mockClient: jest.Mocked;
-
- beforeEach(() => {
- mockClient = {
- tweet: jest.fn().mockResolvedValue(mockApiResponse),
- } as unknown as jest.Mocked;
-
- mockApi = {
- get v2() {
- return mockClient;
- },
- } as unknown as jest.Mocked;
- });
-
- it("should successfully post a reply", async () => {
- const args = {
- tweetId: MOCK_TWEET_ID,
- tweetReply: MOCK_TWEET_REPLY,
- };
-
- const response = await postTweet(mockApi, args);
-
- expect(mockApi.v2.tweet).toHaveBeenCalledWith(MOCK_TWEET_REPLY, {
- reply: { in_reply_to_tweet_id: MOCK_TWEET_ID },
- });
- expect(response).toContain("Successfully posted reply to Twitter:");
- expect(response).toContain(JSON.stringify(mockApiResponse));
- });
-
- it("should handle errors when posting a reply", async () => {
- const args = {
- tweetId: MOCK_TWEET_ID,
- tweetReply: MOCK_TWEET_REPLY,
- };
-
- const error = new Error("An error has occurred");
- mockClient.tweet.mockRejectedValue(error);
-
- const response = await postTweet(mockApi, args);
-
- expect(mockApi.v2.tweet).toHaveBeenCalledWith(MOCK_TWEET_REPLY, {
- reply: { in_reply_to_tweet_id: MOCK_TWEET_ID },
- });
- expect(response).toContain("Error posting reply to Twitter:");
- expect(response).toContain(error.message);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/social_twitter_post_tweet_test.ts b/cdp-agentkit-core/typescript/src/tests/social_twitter_post_tweet_test.ts
deleted file mode 100644
index 09e461724..000000000
--- a/cdp-agentkit-core/typescript/src/tests/social_twitter_post_tweet_test.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-import { postTweet, PostTweetInput } from "../actions/cdp/social/twitter/post_tweet";
-import { TwitterApi, TwitterApiv2 } from "twitter-api-v2";
-
-const MOCK_TWEET = "@CDPAgentkit please reply!";
-
-describe("Post Tweet Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = { tweet: MOCK_TWEET };
- const result = PostTweetInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail to parse empty input", () => {
- const emptyInput = {};
- const result = PostTweetInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- expect(result.error!.issues[0].message).toBe("Required");
- });
-
- it("should fail to parse invalid input: tweet is too long", () => {
- const invalidInput = { tweet: "A".repeat(281) };
- const result = PostTweetInput.safeParse(invalidInput);
-
- expect(result.success).toBe(false);
- expect(result.error!.issues[0].message).toBe("Tweet must be a maximum of 280 characters.");
- });
-});
-
-describe("Post Tweet Action", () => {
- const mockApiResponse = {
- data: {
- id: "0123456789012345678",
- edit_history_tweet_ids: ["0123456789012345678"],
- text: MOCK_TWEET,
- },
- };
-
- let mockApi: jest.Mocked;
- let mockClient: jest.Mocked;
-
- beforeEach(() => {
- mockClient = {
- tweet: jest.fn().mockResolvedValue(mockApiResponse),
- } as unknown as jest.Mocked;
-
- mockApi = {
- get v2() {
- return mockClient;
- },
- } as unknown as jest.Mocked;
- });
-
- it("should successfully post a tweet", async () => {
- const args = {
- tweet: "Hello, world!",
- };
-
- const response = await postTweet(mockApi, args);
-
- expect(mockApi.v2.tweet).toHaveBeenCalledWith(args.tweet);
- expect(response).toContain("Successfully posted to Twitter:");
- expect(response).toContain(JSON.stringify(mockApiResponse));
- });
-
- it("should handle errors when posting a tweet", async () => {
- const args = {
- tweet: "Hello, world!",
- };
-
- const error = new Error("An error has occurred");
- mockClient.tweet.mockRejectedValue(error);
-
- const response = await postTweet(mockApi, { tweet: "Hello, world!" });
-
- expect(mockApi.v2.tweet).toHaveBeenCalledWith(args.tweet);
- expect(response).toContain("Error posting to Twitter:");
- expect(response).toContain(error.message);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/trade_test.ts b/cdp-agentkit-core/typescript/src/tests/trade_test.ts
deleted file mode 100644
index 89804a2c0..000000000
--- a/cdp-agentkit-core/typescript/src/tests/trade_test.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-import { Coinbase, Trade, Wallet } from "@coinbase/coinbase-sdk";
-
-import { trade as createTrade, TradeInput } from "../actions/cdp/trade";
-
-const MOCK_TRADE_AMOUNT = 0.123;
-const MOCK_TRADE_ASSET_ID_FROM = Coinbase.assets.Eth;
-const MOCK_TRADE_ASSET_ID_TO = Coinbase.assets.Usdc;
-
-describe("Trade Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- amount: MOCK_TRADE_AMOUNT,
- fromAssetId: MOCK_TRADE_ASSET_ID_FROM,
- toAssetId: MOCK_TRADE_ASSET_ID_TO,
- };
-
- const result = TradeInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = TradeInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Trade Action", () => {
- const TO_AMOUNT = 3661.08;
- const TRANSACTION_HASH = "0xghijkl987654321";
- const TRANSACTION_LINK = `https://etherscan.io/tx/${TRANSACTION_HASH}`;
-
- let mockTrade: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(async () => {
- mockTrade = {
- wait: jest.fn().mockResolvedValue({
- getToAmount: jest.fn().mockReturnValue(TO_AMOUNT),
- getTransaction: jest.fn().mockReturnValue({
- getTransactionHash: jest.fn().mockReturnValue(TRANSACTION_HASH),
- getTransactionLink: jest.fn().mockReturnValue(TRANSACTION_LINK),
- }),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet = {
- createTrade: jest.fn(),
- } as unknown as jest.Mocked;
-
- mockWallet.createTrade.mockResolvedValue(mockTrade);
- });
-
- it("should successfully execute the trade", async () => {
- const args = {
- amount: MOCK_TRADE_AMOUNT,
- fromAssetId: MOCK_TRADE_ASSET_ID_FROM,
- toAssetId: MOCK_TRADE_ASSET_ID_TO,
- };
-
- const response = await createTrade(mockWallet, args);
-
- expect(mockWallet.createTrade).toHaveBeenCalledWith(args);
- expect(mockTrade.wait).toHaveBeenCalled();
- expect(response).toContain(
- `Traded ${MOCK_TRADE_AMOUNT} of ${MOCK_TRADE_ASSET_ID_FROM} for ${TO_AMOUNT} of ${MOCK_TRADE_ASSET_ID_TO}`,
- );
- expect(response).toContain(`Transaction hash for the trade: ${TRANSACTION_HASH}`);
- expect(response).toContain(`Transaction link for the trade: ${TRANSACTION_LINK}`);
- });
-
- it("should fail with an error", async () => {
- const args = {
- amount: MOCK_TRADE_AMOUNT,
- fromAssetId: MOCK_TRADE_ASSET_ID_FROM,
- toAssetId: MOCK_TRADE_ASSET_ID_TO,
- };
-
- const error = new Error("Failed to execute trade");
- mockWallet.createTrade.mockRejectedValue(error);
-
- const response = await createTrade(mockWallet, args);
-
- expect(mockWallet.createTrade).toHaveBeenCalled();
- expect(response).toContain(`Error trading assets: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/transfer_nft_test.ts b/cdp-agentkit-core/typescript/src/tests/transfer_nft_test.ts
deleted file mode 100644
index 2c1a0dc16..000000000
--- a/cdp-agentkit-core/typescript/src/tests/transfer_nft_test.ts
+++ /dev/null
@@ -1,142 +0,0 @@
-import { ContractInvocation, Wallet } from "@coinbase/coinbase-sdk";
-
-import { transferNft, TransferNftInput } from "../actions/cdp/transfer_nft";
-
-const MOCK_CONTRACT_ADDRESS = "0x123456789abcdef";
-const MOCK_TOKEN_ID = "1000";
-const MOCK_DESTINATION = "0xabcdef123456789";
-const MOCK_FROM_ADDRESS = "0xdefault123456789";
-
-describe("Transfer NFT Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- tokenId: MOCK_TOKEN_ID,
- destination: MOCK_DESTINATION,
- fromAddress: MOCK_FROM_ADDRESS,
- };
-
- const result = TransferNftInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should successfully parse input without optional fromAddress", () => {
- const validInput = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- tokenId: MOCK_TOKEN_ID,
- destination: MOCK_DESTINATION,
- };
-
- const result = TransferNftInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = TransferNftInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Transfer NFT Action", () => {
- const TRANSACTION_HASH = "0xghijkl987654321";
- const TRANSACTION_LINK = `https://etherscan.io/tx/${TRANSACTION_HASH}`;
-
- let mockContractInvocation: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockContractInvocation = {
- wait: jest.fn().mockResolvedValue({
- getTransaction: jest.fn().mockReturnValue({
- getTransactionHash: jest.fn().mockReturnValue(TRANSACTION_HASH),
- getTransactionLink: jest.fn().mockReturnValue(TRANSACTION_LINK),
- }),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet = {
- invokeContract: jest.fn(),
- getDefaultAddress: jest.fn().mockResolvedValue({
- getId: jest.fn().mockReturnValue(MOCK_FROM_ADDRESS),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet.invokeContract.mockResolvedValue(mockContractInvocation);
- });
-
- it("should successfully transfer NFT with provided fromAddress", async () => {
- const args = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- tokenId: MOCK_TOKEN_ID,
- destination: MOCK_DESTINATION,
- fromAddress: MOCK_FROM_ADDRESS,
- };
-
- const response = await transferNft(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalledWith({
- contractAddress: MOCK_CONTRACT_ADDRESS,
- method: "transferFrom",
- args: {
- from: MOCK_FROM_ADDRESS,
- to: MOCK_DESTINATION,
- tokenId: MOCK_TOKEN_ID,
- },
- });
- expect(mockContractInvocation.wait).toHaveBeenCalled();
- expect(response).toContain(
- `Transferred NFT (ID: ${MOCK_TOKEN_ID}) from contract ${MOCK_CONTRACT_ADDRESS} to ${MOCK_DESTINATION}`,
- );
- expect(response).toContain(`Transaction hash: ${TRANSACTION_HASH}`);
- expect(response).toContain(`Transaction link: ${TRANSACTION_LINK}`);
- });
-
- it("should successfully transfer NFT with default address", async () => {
- const args = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- tokenId: MOCK_TOKEN_ID,
- destination: MOCK_DESTINATION,
- };
-
- const response = await transferNft(mockWallet, args);
-
- expect(mockWallet.getDefaultAddress).toHaveBeenCalled();
- expect(mockWallet.invokeContract).toHaveBeenCalledWith({
- contractAddress: MOCK_CONTRACT_ADDRESS,
- method: "transferFrom",
- args: {
- from: MOCK_FROM_ADDRESS,
- to: MOCK_DESTINATION,
- tokenId: MOCK_TOKEN_ID,
- },
- });
- expect(mockContractInvocation.wait).toHaveBeenCalled();
- expect(response).toContain(
- `Transferred NFT (ID: ${MOCK_TOKEN_ID}) from contract ${MOCK_CONTRACT_ADDRESS} to ${MOCK_DESTINATION}`,
- );
- });
-
- it("should fail with an error", async () => {
- const args = {
- contractAddress: MOCK_CONTRACT_ADDRESS,
- tokenId: MOCK_TOKEN_ID,
- destination: MOCK_DESTINATION,
- };
-
- const error = new Error("Failed to transfer NFT");
- mockWallet.invokeContract.mockRejectedValue(error);
-
- const response = await transferNft(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalled();
- expect(response).toContain(
- `Error transferring the NFT (contract: ${MOCK_CONTRACT_ADDRESS}, ID: ${MOCK_TOKEN_ID}) from ${MOCK_FROM_ADDRESS} to ${MOCK_DESTINATION}): ${error}`,
- );
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/transfer_test.ts b/cdp-agentkit-core/typescript/src/tests/transfer_test.ts
deleted file mode 100644
index bf3caf7e8..000000000
--- a/cdp-agentkit-core/typescript/src/tests/transfer_test.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-import { Coinbase, Transfer, Wallet } from "@coinbase/coinbase-sdk";
-
-import { transfer as createTransfer, TransferInput } from "../actions/cdp/transfer";
-
-const MOCK_AMOUNT = 15;
-const MOCK_ASSET_ID = Coinbase.assets.Eth;
-const MOCK_DESTINATION = "0x321";
-const MOCK_GASLESS = true;
-
-describe("Transfer Input", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- amount: MOCK_AMOUNT,
- assetId: MOCK_ASSET_ID,
- destination: MOCK_DESTINATION,
- gasless: MOCK_GASLESS,
- };
-
- const result = TransferInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = TransferInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Transfer Action", () => {
- const TRANSACTION_HASH = "0xghijkl987654321";
- const TRANSACTION_LINK = `https://etherscan.io/tx/${TRANSACTION_HASH}`;
-
- let mockTransfer: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(async () => {
- mockTransfer = {
- wait: jest.fn().mockResolvedValue({
- getTransactionHash: jest.fn().mockReturnValue(TRANSACTION_HASH),
- getTransactionLink: jest.fn().mockReturnValue(TRANSACTION_LINK),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet = {
- createTransfer: jest.fn(),
- } as unknown as jest.Mocked;
-
- mockWallet.createTransfer.mockResolvedValue(mockTransfer);
- });
-
- it("should successfully respond", async () => {
- const args = {
- amount: MOCK_AMOUNT,
- assetId: MOCK_ASSET_ID,
- destination: MOCK_DESTINATION,
- gasless: MOCK_GASLESS,
- };
-
- const response = await createTransfer(mockWallet, args);
-
- expect(mockWallet.createTransfer).toHaveBeenCalledWith(args);
- expect(mockTransfer.wait).toHaveBeenCalled();
- expect(response).toContain(
- `Transferred ${MOCK_AMOUNT} of ${MOCK_ASSET_ID} to ${MOCK_DESTINATION}`,
- );
- expect(response).toContain(`Transaction hash for the transfer: ${TRANSACTION_HASH}`);
- expect(response).toContain(`Transaction link for the transfer: ${TRANSACTION_LINK}`);
- });
-
- it("should fail with an error", async () => {
- const args = {
- amount: MOCK_AMOUNT,
- assetId: MOCK_ASSET_ID,
- destination: MOCK_DESTINATION,
- gasless: MOCK_GASLESS,
- };
-
- const error = new Error("Failed to execute transfer");
- mockWallet.createTransfer.mockRejectedValue(error);
-
- const response = await createTransfer(mockWallet, args);
-
- expect(mockWallet.createTransfer).toHaveBeenCalledWith(args);
- expect(response).toContain(`Error transferring the asset: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/utils_test.ts b/cdp-agentkit-core/typescript/src/tests/utils_test.ts
deleted file mode 100644
index 105dcfd6e..000000000
--- a/cdp-agentkit-core/typescript/src/tests/utils_test.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import { ContractInvocation, Wallet } from "@coinbase/coinbase-sdk";
-import { approve } from "../actions/cdp/utils";
-
-const MOCK_TOKEN_ADDRESS = "0x123456789abcdef";
-const MOCK_SPENDER_ADDRESS = "0xabcdef123456789";
-const MOCK_AMOUNT = BigInt(1000000);
-const TRANSACTION_HASH = "0xghijkl987654321";
-
-describe("Utils - Approve", () => {
- let mockContractInvocation: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockContractInvocation = {
- wait: jest.fn().mockResolvedValue({
- getTransactionHash: jest.fn().mockReturnValue(TRANSACTION_HASH),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet = {
- invokeContract: jest.fn(),
- } as unknown as jest.Mocked;
-
- mockWallet.invokeContract.mockResolvedValue(mockContractInvocation);
- });
-
- it("should successfully approve tokens", async () => {
- const response = await approve(
- mockWallet,
- MOCK_TOKEN_ADDRESS,
- MOCK_SPENDER_ADDRESS,
- MOCK_AMOUNT,
- );
-
- expect(mockWallet.invokeContract).toHaveBeenCalledWith({
- contractAddress: MOCK_TOKEN_ADDRESS,
- method: "approve",
- abi: expect.any(Array),
- args: {
- spender: MOCK_SPENDER_ADDRESS,
- value: MOCK_AMOUNT.toString(),
- },
- });
- expect(mockContractInvocation.wait).toHaveBeenCalled();
- expect(response).toBe(
- `Approved ${MOCK_AMOUNT} tokens for ${MOCK_SPENDER_ADDRESS} with transaction hash: ${TRANSACTION_HASH}`,
- );
- });
-
- it("should handle approval errors", async () => {
- const error = new Error("Approval failed");
- mockWallet.invokeContract.mockRejectedValue(error);
-
- const response = await approve(
- mockWallet,
- MOCK_TOKEN_ADDRESS,
- MOCK_SPENDER_ADDRESS,
- MOCK_AMOUNT,
- );
-
- expect(mockWallet.invokeContract).toHaveBeenCalled();
- expect(response).toBe(`Error approving tokens: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/tests/wrap_eth_test.ts b/cdp-agentkit-core/typescript/src/tests/wrap_eth_test.ts
deleted file mode 100644
index 0d13eebc3..000000000
--- a/cdp-agentkit-core/typescript/src/tests/wrap_eth_test.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import { ContractInvocation, Wallet } from "@coinbase/coinbase-sdk";
-
-import { WETH_ABI, WETH_ADDRESS, wrapEth, WrapEthInput } from "../actions/cdp/wrap_eth";
-
-const MOCK_AMOUNT_TO_WRAP = "100000000000000000";
-
-describe("Wrap Eth", () => {
- it("should successfully parse valid input", () => {
- const validInput = {
- amountToWrap: MOCK_AMOUNT_TO_WRAP,
- };
-
- const result = WrapEthInput.safeParse(validInput);
-
- expect(result.success).toBe(true);
- expect(result.data).toEqual(validInput);
- });
-
- it("should fail parsing empty input", () => {
- const emptyInput = {};
- const result = WrapEthInput.safeParse(emptyInput);
-
- expect(result.success).toBe(false);
- });
-});
-
-describe("Wrap Eth Action", () => {
- const TRANSACTION_HASH = "0xghijkl987654321";
-
- let mockContractInvocation: jest.Mocked;
- let mockWallet: jest.Mocked;
-
- beforeEach(() => {
- mockWallet = {
- invokeContract: jest.fn(),
- } as unknown as jest.Mocked;
-
- mockContractInvocation = {
- wait: jest.fn().mockResolvedValue({
- getTransaction: jest.fn().mockReturnValue({
- getTransactionHash: jest.fn().mockReturnValue(TRANSACTION_HASH),
- }),
- }),
- } as unknown as jest.Mocked;
-
- mockWallet.invokeContract.mockResolvedValue(mockContractInvocation);
- });
-
- it("should successfully wrap ETH", async () => {
- const args = {
- amountToWrap: MOCK_AMOUNT_TO_WRAP,
- };
-
- const response = await wrapEth(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalledWith({
- contractAddress: WETH_ADDRESS,
- method: "deposit",
- abi: WETH_ABI,
- args: {},
- amount: BigInt(args.amountToWrap),
- assetId: "wei",
- });
- expect(response).toContain(`Wrapped ETH with transaction hash: ${TRANSACTION_HASH}`);
- });
-
- it("should fail with an error", async () => {
- const args = {
- amountToWrap: MOCK_AMOUNT_TO_WRAP,
- };
-
- const error = new Error("Failed to execute transfer");
- mockWallet.invokeContract.mockRejectedValue(error);
-
- const response = await wrapEth(mockWallet, args);
-
- expect(mockWallet.invokeContract).toHaveBeenCalled();
- expect(response).toContain(`Error wrapping ETH: ${error}`);
- });
-});
diff --git a/cdp-agentkit-core/typescript/src/twitter_agentkit.ts b/cdp-agentkit-core/typescript/src/twitter_agentkit.ts
deleted file mode 100644
index f416f119c..000000000
--- a/cdp-agentkit-core/typescript/src/twitter_agentkit.ts
+++ /dev/null
@@ -1,129 +0,0 @@
-import { TwitterApi, TwitterApiTokens } from "twitter-api-v2";
-import { z } from "zod";
-import { TwitterAction, TwitterActionSchemaAny } from "./actions/cdp/social/twitter";
-
-/**
- * Schema for the options required to initialize the TwitterAgentkit.
- */
-export const TwitterAgentkitOptions = z
- .object({
- apiKey: z
- .string()
- .min(1, "The Twitter (X) API key is required")
- .describe("The Twitter (X) API key"),
- apiSecret: z
- .string()
- .min(1, "The Twitter (X) API secret is required")
- .describe("The Twitter (X) API secret"),
- accessToken: z
- .string()
- .min(1, "The Twitter (X) access token is required")
- .describe("The Twitter (X) access token"),
- accessTokenSecret: z
- .string()
- .min(1, "The Twitter (X) access token secret is required")
- .describe("The Twitter (X) access token secret"),
- })
- .strip()
- .describe("Options for initializing TwitterAgentkit");
-
-/**
- * Schema for the environment variables required for TwitterAgentkit.
- */
-const EnvSchema = z.object({
- TWITTER_API_KEY: z
- .string()
- .min(1, "TWITTER_API_KEY is required")
- .describe("The Twitter (X) API key"),
- TWITTER_API_SECRET: z
- .string()
- .min(1, "TWITTER_API_SECRET is required")
- .describe("The Twitter (X) API secret"),
- TWITTER_ACCESS_TOKEN: z
- .string()
- .min(1, "TWITTER_ACCESS_TOKEN is required")
- .describe("The Twitter (X) access token"),
- TWITTER_ACCESS_TOKEN_SECRET: z
- .string()
- .min(1, "TWITTER_ACCESS_TOKEN_SECRET is required")
- .describe("The Twitter (X) access token secret"),
-});
-
-/**
- * Twitter Agentkit
- */
-export class TwitterAgentkit {
- private client: TwitterApi;
-
- /**
- * Initializes a new instance of TwitterAgentkit with the provided options.
- * If no options are provided, it attempts to load the required environment variables.
- *
- * @param options - Optional. The configuration options for the TwitterAgentkit.
- * @throws An error if the provided options are invalid or if the environment variables cannot be loaded.
- */
- public constructor(options?: z.infer) {
- if (!options) {
- try {
- const env = EnvSchema.parse(process.env);
-
- options = {
- apiKey: env.TWITTER_API_KEY!,
- apiSecret: env.TWITTER_API_SECRET!,
- accessToken: env.TWITTER_ACCESS_TOKEN!,
- accessTokenSecret: env.TWITTER_ACCESS_TOKEN_SECRET!,
- };
- } catch (error) {
- if (error instanceof z.ZodError) {
- error.errors.forEach(err => console.log(`Error: ${err.path[0]} is required`));
- }
- throw new Error("Twitter (X) ENV could not be loaded.");
- }
- }
-
- if (!this.validateOptions(options)) {
- throw new Error("Twitter (X) Agentkit options could not be validated.");
- }
-
- this.client = new TwitterApi({
- appKey: options.apiKey,
- appSecret: options.apiSecret,
- accessToken: options.accessToken,
- accessSecret: options.accessTokenSecret,
- } as TwitterApiTokens);
- }
-
- /**
- * Validates the provided options for the TwitterAgentkit.
- *
- * @param options - The options to validate.
- * @returns True if the options are valid, otherwise false.
- */
- validateOptions(options: z.infer): boolean {
- try {
- TwitterAgentkitOptions.parse(options);
- } catch (error) {
- if (error instanceof z.ZodError) {
- error.errors.forEach(err => console.log("Error:", err.message));
- }
-
- return false;
- }
-
- return true;
- }
-
- /**
- * Executes a Twitter (X) action.
- *
- * @param action - The Twitter (X) action to execute.
- * @param args - The arguments for the action.
- * @returns The result of the execution.
- */
- async run(
- action: TwitterAction,
- args: TActionSchema,
- ): Promise {
- return await action.func(this.client, args);
- }
-}
diff --git a/cdp-langchain/README.md b/cdp-langchain/README.md
deleted file mode 100644
index a8ae116cd..000000000
--- a/cdp-langchain/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# CDP Agentkit Extension - Langchain Toolkit
-
-CDP integration with Langchain to enable agentic workflows using the core primitives defined in `cdp-agentkit-core`.
-
-This toolkit contains tools that enable an LLM agent to interact with the [Coinbase Developer Platform](https://docs.cdp.coinbase.com/). The toolkit provides a wrapper around the CDP SDK, allowing agents to perform onchain operations like transfers, trades, and smart contract interactions.
-
-For Python, see [cdp-langchain/python](./python/README.md).
-For TypeScript, see [cdp-langchain/typescript](./typescript/README.md).
\ No newline at end of file
diff --git a/cdp-langchain/examples/chatbot-typescript/.env.example b/cdp-langchain/examples/chatbot-typescript/.env.example
deleted file mode 100644
index 38e3bbfd8..000000000
--- a/cdp-langchain/examples/chatbot-typescript/.env.example
+++ /dev/null
@@ -1,3 +0,0 @@
-CDP_API_KEY_NAME="" # Place your CDP API key name in between the quotes
-CDP_API_KEY_PRIVATE_KEY="" # Place your CDP API key private key in between the quotes
-OPENAI_API_KEY="" # Place your OpenAI API key in between the quotes
diff --git a/cdp-langchain/python/docs/README.md b/cdp-langchain/python/docs/README.md
deleted file mode 120000
index 32d46ee88..000000000
--- a/cdp-langchain/python/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-../README.md
\ No newline at end of file
diff --git a/cdp-langchain/typescript/.eslintrc.json b/cdp-langchain/typescript/.eslintrc.json
deleted file mode 100644
index 91571ba7a..000000000
--- a/cdp-langchain/typescript/.eslintrc.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "parser": "@typescript-eslint/parser",
- "extends": ["../../.eslintrc.base.json"]
-}
diff --git a/cdp-langchain/typescript/jest.config.cjs b/cdp-langchain/typescript/jest.config.cjs
deleted file mode 100644
index 2dceab682..000000000
--- a/cdp-langchain/typescript/jest.config.cjs
+++ /dev/null
@@ -1,14 +0,0 @@
-const baseConfig = require("../../jest.config.base.cjs");
-
-module.exports = {
- ...baseConfig,
- coveragePathIgnorePatterns: ["node_modules", "dist", "docs", "index.ts"],
- coverageThreshold: {
- "./src/**": {
- branches: 30,
- functions: 50,
- statements: 50,
- lines: 50,
- },
- },
-};
diff --git a/cdp-langchain/typescript/src/index.ts b/cdp-langchain/typescript/src/index.ts
deleted file mode 100644
index 72d1dcfff..000000000
--- a/cdp-langchain/typescript/src/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * Main exports for the CDP Langchain package
- */
-
-// Export core toolkit components
-export { CdpToolkit } from "./toolkits/cdp_toolkit";
-export { CdpTool } from "./tools/cdp_tool";
-
-// Export types
-export type { Tool } from "@langchain/core/tools";
diff --git a/cdp-langchain/typescript/src/tests/cdp_tool_test.ts b/cdp-langchain/typescript/src/tests/cdp_tool_test.ts
deleted file mode 100644
index 2ecf6bcac..000000000
--- a/cdp-langchain/typescript/src/tests/cdp_tool_test.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import { CdpAction, CdpActionSchemaAny, CdpAgentkit } from "@coinbase/cdp-agentkit-core";
-import { CdpTool } from "../tools/cdp_tool";
-import { z } from "zod";
-
-const MOCK_DESCRIPTION = "CDP Test Action";
-const MOCK_NAME = "get_wallet_details";
-
-describe("CdpTool", () => {
- let mockAgentkit: jest.Mocked;
- let mockAction: jest.Mocked>;
- let cdpTool: CdpTool;
-
- beforeEach(() => {
- mockAgentkit = {
- run: jest.fn((action, args) => action.func(args)),
- wallet: {
- getDefaultAddress: jest.fn().mockResolvedValue({ getId: () => "mock-address" }),
- },
- } as unknown as jest.Mocked;
-
- mockAction = {
- name: MOCK_NAME,
- description: MOCK_DESCRIPTION,
- argsSchema: z.object({ wallet_id: z.string() }),
- func: jest.fn().mockResolvedValue("Wallet details retrieved successfully"),
- } as unknown as jest.Mocked>;
-
- cdpTool = new CdpTool(mockAction, mockAgentkit);
- });
-
- it("should initialize with correct properties", () => {
- expect(cdpTool.name).toBe(MOCK_NAME);
- expect(cdpTool.description).toBe(MOCK_DESCRIPTION);
- expect(cdpTool.schema).toEqual(mockAction.argsSchema);
- });
-
- it("should execute action with valid args", async () => {
- const args = { wallet_id: "0x123" };
- const response = await cdpTool.call(args);
-
- expect(mockAction.func).toHaveBeenCalledWith(args);
- expect(response).toBe("Wallet details retrieved successfully");
- });
-
- it("should handle schema validation errors", async () => {
- const invalidArgs = { invalid_param: "test" };
- await expect(cdpTool.call(invalidArgs)).rejects.toThrow();
- expect(mockAction.func).not.toHaveBeenCalled();
- });
-
- it("should return error message on action execution failure", async () => {
- mockAction.func.mockRejectedValue(new Error("Failed to retrieve wallet details"));
- const args = { wallet_id: "0x123" };
- const response = await cdpTool.call(args);
- expect(response).toContain(
- "Error executing get_wallet_details: Failed to retrieve wallet details",
- );
- });
-});
diff --git a/cdp-langchain/typescript/src/tests/cdp_toolkit_test.ts b/cdp-langchain/typescript/src/tests/cdp_toolkit_test.ts
deleted file mode 100644
index 7733e218f..000000000
--- a/cdp-langchain/typescript/src/tests/cdp_toolkit_test.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import { CdpToolkit } from "../toolkits/cdp_toolkit";
-import { CdpTool } from "../tools/cdp_tool";
-import { CdpAction, CdpActionSchemaAny, CdpAgentkit } from "@coinbase/cdp-agentkit-core";
-import { z } from "zod";
-
-describe("CdpToolkit", () => {
- let mockAgentkit: jest.Mocked;
- let mockActions: jest.Mocked>[];
- let cdpToolkit: CdpToolkit;
-
- beforeEach(() => {
- mockAgentkit = {
- run: jest.fn((action, args) => action.func(args)),
- wallet: {
- getDefaultAddress: jest.fn().mockResolvedValue({ getId: () => "mock-address" }),
- },
- } as unknown as jest.Mocked;
-
- mockActions = [
- {
- name: "get_wallet_details",
- description: "Get wallet details",
- argsSchema: z.object({ param1: z.string() }),
- func: jest.fn().mockResolvedValue("success_1"),
- },
- {
- name: "get_balance",
- description: "Get wallet balance",
- argsSchema: z.object({ param2: z.string() }),
- func: jest.fn().mockResolvedValue("success_2"),
- },
- ];
-
- cdpToolkit = new CdpToolkit(mockAgentkit);
- cdpToolkit.tools = mockActions.map(action => new CdpTool(action, mockAgentkit));
- });
-
- it("should initialize with correct tools", () => {
- expect(cdpToolkit.tools).toHaveLength(mockActions.length);
- expect(cdpToolkit.tools[0].name).toBe("get_wallet_details");
- expect(cdpToolkit.tools[1].name).toBe("get_balance");
- });
-
- it("should execute action from toolkit", async () => {
- const tool = cdpToolkit.tools[0];
- const args = { param1: "test" };
- const response = await tool.call(args);
-
- expect(mockActions[0].func).toHaveBeenCalledWith(args);
- expect(response).toBe("success_1");
- });
-
- it("should handle action execution failure", async () => {
- const error = new Error("Execution failed");
- mockActions[0].func.mockRejectedValue(error);
-
- const tool = cdpToolkit.tools[0];
- const args = { param1: "test" };
- const response = await tool.call(args);
-
- expect(response).toContain(`Error executing get_wallet_details: ${error.message}`);
- });
-
- it("should return all available tools", () => {
- const tools = cdpToolkit.getTools();
-
- expect(tools).toHaveLength(mockActions.length);
- expect(tools[0].name).toBe("get_wallet_details");
- expect(tools[1].name).toBe("get_balance");
- });
-});
diff --git a/cdp-langchain/typescript/src/toolkits/cdp_toolkit.ts b/cdp-langchain/typescript/src/toolkits/cdp_toolkit.ts
deleted file mode 100644
index 10a7015b7..000000000
--- a/cdp-langchain/typescript/src/toolkits/cdp_toolkit.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { StructuredToolInterface, BaseToolkit as Toolkit } from "@langchain/core/tools";
-import { CDP_ACTIONS, CdpAgentkit } from "@coinbase/cdp-agentkit-core";
-import { CdpTool } from "../tools/cdp_tool";
-
-/**
- * Coinbase Developer Platform (CDP) Toolkit.
- *
- * Security Note: This toolkit contains tools that can read and modify
- * the state of a service; e.g., by creating, deleting, or updating,
- * reading underlying data.
- *
- * For example, this toolkit can be used to create wallets, transactions,
- * and smart contract invocations on CDP supported blockchains.
- *
- * Setup:
- * You will need to set the following environment variables:
- * ```bash
- * export CDP_API_KEY_NAME="cdp-api-key-name"
- * export CDP_API_KEY_PRIVATE_KEY="cdp-api-key-private-key"
- * export NETWORK_ID="network-id"
- * ```
- *
- * Example usage:
- * ```typescript
- * const agentkit = await CdpAgentkit.configureWithWallet();
- * const toolkit = new CdpToolkit(agentkit);
- * const tools = toolkit.getTools();
- *
- * // Available tools include:
- * // - get_wallet_details
- * // - get_balance
- * // - get_balance_nft
- * // - request_faucet_funds
- * // - transfer
- * // - transfer_nft
- * // - trade
- * // - deploy_token
- * // - deploy_contract
- * // - mint_nft
- * // - deploy_nft
- * // - register_basename
- * // - wow_create_token
- * // - wow_buy_token
- * // - wow_sell_token
- * // - wrap_eth
- * ```
- */
-export class CdpToolkit extends Toolkit {
- tools: StructuredToolInterface[];
-
- /**
- * Creates a new CDP Toolkit instance
- *
- * @param agentkit - CDP agentkit instance
- */
- constructor(agentkit: CdpAgentkit) {
- super();
- const actions = CDP_ACTIONS;
- const tools = actions.map(action => new CdpTool(action, agentkit));
- this.tools = tools;
- }
-}
diff --git a/cdp-langchain/typescript/src/tools/cdp_tool.ts b/cdp-langchain/typescript/src/tools/cdp_tool.ts
deleted file mode 100644
index 5223b24a2..000000000
--- a/cdp-langchain/typescript/src/tools/cdp_tool.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-import { StructuredTool } from "@langchain/core/tools";
-import { CdpAgentkit, CdpAction, CdpActionSchemaAny } from "@coinbase/cdp-agentkit-core";
-import { z } from "zod";
-
-/**
- * This tool allows agents to interact with the cdp-sdk library and control an MPC Wallet onchain.
- *
- * To use this tool, you must first set as environment variables:
- * CDP_API_KEY_NAME
- * CDP_API_KEY_PRIVATE_KEY
- * NETWORK_ID
- */
-export class CdpTool extends StructuredTool {
- /**
- * Schema definition for the tool's input
- */
- public schema: TActionSchema;
-
- /**
- * The name of the tool
- */
- public name: string;
-
- /**
- * The description of the tool
- */
- public description: string;
-
- /**
- * The CDP Agentkit instance
- */
- private agentkit: CdpAgentkit;
-
- /**
- * The CDP Action
- */
- private action: CdpAction;
-
- /**
- * Constructor for the CDP Tool class
- *
- * @param action - The CDP action to execute
- * @param agentkit - The CDP wrapper to use
- */
- constructor(action: CdpAction, agentkit: CdpAgentkit) {
- super();
- this.action = action;
- this.agentkit = agentkit;
- this.name = action.name;
- this.description = action.description;
- this.schema = action.argsSchema;
- }
-
- /**
- * Executes the CDP action with the provided input
- *
- * @param input - An object containing either instructions or schema-validated arguments
- * @returns A promise that resolves to the result of the CDP action
- * @throws {Error} If the CDP action fails
- */
- protected async _call(
- input: z.infer & Record,
- ): Promise {
- try {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- let args: any;
-
- // If we have a schema, try to validate against it
- if (this.schema) {
- try {
- const validatedInput = this.schema.parse(input);
- args = validatedInput;
- } catch (validationError) {
- // If schema validation fails, fall back to instructions-only mode
- args = input;
- }
- }
- // No schema, use instructions mode
- else {
- args = input;
- }
-
- return await this.agentkit.run(this.action, args);
- } catch (error: unknown) {
- if (error instanceof Error) {
- return `Error executing ${this.name}: ${error.message}`;
- }
- return `Error executing ${this.name}: Unknown error occurred`;
- }
- }
-}
diff --git a/cdp-langchain/typescript/tsconfig.json b/cdp-langchain/typescript/tsconfig.json
deleted file mode 100644
index 2e2cc2c33..000000000
--- a/cdp-langchain/typescript/tsconfig.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "extends": "../../tsconfig.base.json",
- "compilerOptions": {
- "outDir": "./dist",
- "rootDir": "./src"
- },
- "include": ["src/**/*.ts"],
- "exclude": ["src/tests"]
-}
diff --git a/farcaster-langchain/README.md b/farcaster-langchain/README.md
deleted file mode 100644
index 873a475a3..000000000
--- a/farcaster-langchain/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# CDP Agentkit Extension - Farcaster Langchain Toolkit
-
-This toolkit contains tools that enable an LLM agent to interact with Farcaster using Neynar's API. The toolkit provides a wrapper around the Neynar API, allowing agents to interact with Farcaster and perform actions like posting casts.
-
-For TypeScript, see [farcaster-langchain/typescript](./typescript/README.md).
diff --git a/farcaster-langchain/examples/chatbot-typescript/.prettierignore b/farcaster-langchain/examples/chatbot-typescript/.prettierignore
deleted file mode 100644
index a6949181a..000000000
--- a/farcaster-langchain/examples/chatbot-typescript/.prettierignore
+++ /dev/null
@@ -1,7 +0,0 @@
-docs/
-dist/
-coverage/
-.github/
-src/client
-**/**/*.json
-*.md
\ No newline at end of file
diff --git a/farcaster-langchain/examples/chatbot-typescript/.prettierrc b/farcaster-langchain/examples/chatbot-typescript/.prettierrc
deleted file mode 100644
index ffb416b74..000000000
--- a/farcaster-langchain/examples/chatbot-typescript/.prettierrc
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "tabWidth": 2,
- "useTabs": false,
- "semi": true,
- "singleQuote": false,
- "trailingComma": "all",
- "bracketSpacing": true,
- "arrowParens": "avoid",
- "printWidth": 100,
- "proseWrap": "never"
-}
diff --git a/farcaster-langchain/typescript/.eslintrc.json b/farcaster-langchain/typescript/.eslintrc.json
deleted file mode 100644
index 91571ba7a..000000000
--- a/farcaster-langchain/typescript/.eslintrc.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "parser": "@typescript-eslint/parser",
- "extends": ["../../.eslintrc.base.json"]
-}
diff --git a/farcaster-langchain/typescript/.prettierignore b/farcaster-langchain/typescript/.prettierignore
deleted file mode 100644
index 20de531f4..000000000
--- a/farcaster-langchain/typescript/.prettierignore
+++ /dev/null
@@ -1,7 +0,0 @@
-docs/
-dist/
-coverage/
-.github/
-src/client
-**/**/*.json
-*.md
diff --git a/farcaster-langchain/typescript/.prettierrc b/farcaster-langchain/typescript/.prettierrc
deleted file mode 100644
index ffb416b74..000000000
--- a/farcaster-langchain/typescript/.prettierrc
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "tabWidth": 2,
- "useTabs": false,
- "semi": true,
- "singleQuote": false,
- "trailingComma": "all",
- "bracketSpacing": true,
- "arrowParens": "avoid",
- "printWidth": 100,
- "proseWrap": "never"
-}
diff --git a/farcaster-langchain/typescript/CHANGELOG.md b/farcaster-langchain/typescript/CHANGELOG.md
deleted file mode 100644
index 5d7781330..000000000
--- a/farcaster-langchain/typescript/CHANGELOG.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# AgentKit.js Farcaster Langchain Extension Changelog
-
-## [0.0.1] - 2025-01-27
-
-### Added
-
-- Initial release of `@coinbase/farcaster-langchain`.
diff --git a/farcaster-langchain/typescript/README.md b/farcaster-langchain/typescript/README.md
deleted file mode 100644
index 4452f40d6..000000000
--- a/farcaster-langchain/typescript/README.md
+++ /dev/null
@@ -1,65 +0,0 @@
-# CDP Agentkit Extension - Farcaster Langchain Toolkit
-
-This toolkit contains tools that enable an LLM agent to interact with Farcaster using Neynar's API. The toolkit provides a wrapper around the Neynar API, allowing agents to interact with Farcaster and perform actions like posting casts.
-
-## Setup
-
-### Prerequisites
-
-- [Farcaster Account](https://docs.farcaster.xyz/developers/guides/accounts/create-account)
-- [Neynar API Key](https://neynar.com)
-- [Neynar Managed Signer ID](https://docs.neynar.com/docs/integrate-managed-signers)
-- [OpenAI API Key](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)
-- Node.js 18 or higher
-
-### Installation
-
-```bash
-npm install @coinbase/farcaster-langchain
-```
-
-### Environment Setup
-
-Set the following environment variables:
-
-```bash
-export CDP_API_KEY_NAME=
-export CDP_API_KEY_PRIVATE_KEY=$''
-export AGENT_FID=
-export NEYNAR_API_KEY=
-export NEYNAR_MANAGED_SIGNER=
-export OPENAI_API_KEY=
-export NETWORK_ID=base-sepolia # Optional: Defaults to base-sepolia
-```
-
-## Usage
-
-### Basic Setup
-
-```typescript
-import { FarcasterToolkit } from "@coinbase/farcaster-langchain";
-import { FarcasterAgentkit } from "@coinbase/cdp-agentkit-core";
-
-// Initialize LLM
- const llm = new ChatOpenAI({ model: "gpt-4o-mini" });
-
-// Farcaster Agentkit
-const farcasterAgentkit = new FarcasterAgentkit();
-
-// Farcaster Toolkit
-const farcasterToolkit = new FarcasterToolkit(farcasterAgentkit);
-
-// Get available Farcaster tools
-const tools = farcasterToolkit.getTools();
-```
-
-The toolkit provides the following tools:
-
-1. **farcaster_account_details** - Retrieve account details for the agent's Farcaster account
-2. **farcaster_post_cast** - Post a cast to Farcaster
-
-
-## Examples
-
-Check out [farcaster-langchain/examples](./examples) for sample implementations!
-- [Chatbot Typescript](./examples/chatbot-typescript/README.md): Simple example of a Node.js Chatbot that can post casts to Farcaster.
diff --git a/farcaster-langchain/typescript/package.json b/farcaster-langchain/typescript/package.json
deleted file mode 100644
index 9e7d84366..000000000
--- a/farcaster-langchain/typescript/package.json
+++ /dev/null
@@ -1,45 +0,0 @@
-{
- "name": "@coinbase/farcaster-langchain",
- "version": "0.0.1",
- "description": "Farcaster langchain Toolkit extension of CDP Agentkit",
- "repository": "https://github.com/coinbase/agentkit",
- "main": "dist/index.js",
- "types": "dist/index.d.ts",
- "files": ["dist"],
- "scripts": {
- "build": "tsc",
- "lint": "npx --yes eslint -c .eslintrc.json src/**/*.ts",
- "lint:fix": "npx --yes eslint -c .eslintrc.json src/**/*.ts --fix",
- "format": "npx --yes prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"",
- "format-check": "npx --yes prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"",
- "check": "tsc --noEmit",
- "test": "npx jest --no-cache --testMatch='**/*_test.ts'",
- "test:dry-run": "npm install && npm ci && npm publish --dry-run",
- "test:e2e": "npx jest --no-cache --testMatch=**/e2e.ts --coverageThreshold '{}'",
- "test:types": "tsd --files src/tests/types.test-d.ts",
- "clean": "rm -rf dist/*",
- "prepack": "tsc",
- "docs": "npx --yes typedoc --entryPoints ./src --entryPointStrategy expand --exclude ./src/tests/**/*.ts",
- "docs:serve": "http-server ./docs",
- "dev": "tsc --watch"
- },
- "keywords": [
- "cdp",
- "sdk",
- "agentkit",
- "ai",
- "agent",
- "farcaster",
- "nodejs",
- "typescript",
- "langchain"
- ],
- "dependencies": {
- "@coinbase/cdp-agentkit-core": "^0.0.14",
- "@langchain/core": "0.3.30",
- "zod": "^3.22.4"
- },
- "peerDependencies": {
- "@coinbase/coinbase-sdk": "^0.15.0"
- }
-}
diff --git a/farcaster-langchain/typescript/src/farcaster_tool.ts b/farcaster-langchain/typescript/src/farcaster_tool.ts
deleted file mode 100644
index 7999a8464..000000000
--- a/farcaster-langchain/typescript/src/farcaster_tool.ts
+++ /dev/null
@@ -1,96 +0,0 @@
-import { StructuredTool } from "@langchain/core/tools";
-import { z } from "zod";
-import {
- FarcasterAction,
- FarcasterActionSchemaAny,
- FarcasterAgentkit,
-} from "@coinbase/cdp-agentkit-core";
-
-/**
- * This tool allows agents to interact with the Farcaster API and control an authenticated Farcaster account.
- *
- * To use this tool, you must first configure with proper options or
- * set the following environment variables:
- * - AGENT_FID
- * - NEYNAR_API_KEY
- * - NEYNAR_MANAGED_SIGNER
- */
-export class FarcasterTool extends StructuredTool {
- /**
- * Schema definition for the tool's input.
- */
- public schema: TActionSchema;
-
- /**
- * The name of the tool.
- */
- public name: string;
-
- /**
- * The description of the tool.
- */
- public description: string;
-
- /**
- * The Farcaster Agentkit instance.
- */
- private agentkit: FarcasterAgentkit;
-
- /**
- * The Farcaster Action.
- */
- private action: FarcasterAction;
-
- /**
- * Constructor for the Farcaster Tool class.
- *
- * @param action - The Farcaster action to execute.
- * @param agentkit - The Farcaster wrapper to use.
- */
- constructor(action: FarcasterAction, agentkit: FarcasterAgentkit) {
- super();
-
- this.action = action;
- this.agentkit = agentkit;
- this.name = action.name;
- this.description = action.description;
- this.schema = action.argsSchema;
- }
-
- /**
- * Executes the Farcaster action with the provided input.
- *
- * @param input - An object containing either instructions or schema-validated arguments.
- * @returns A promise that resolves to the result of the Farcaster action.
- */
- protected async _call(
- input: z.infer