Skip to content

Commit 209644d

Browse files
authored
Merge pull request #97 from niceberginc/use_tensor
use_tensor
2 parents 4017766 + 1fcd303 commit 209644d

File tree

5 files changed

+254
-1
lines changed

5 files changed

+254
-1
lines changed

agentipy/agent/__init__.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2750,4 +2750,46 @@ def simulate_switchboard_feed(
27502750
from agentipy.tools.use_switchboard import SwitchboardManager
27512751
return SwitchboardManager.simulate_switchboard_feed(self, feed, crossbar_url)
27522752
except Exception as e:
2753-
raise SolanaAgentKitError(f"Failed to simulate Switchboard feed: {e}")
2753+
raise SolanaAgentKitError(f"Failed to simulate Switchboard feed: {e}")
2754+
2755+
def list_nft_for_sale(
2756+
self,
2757+
price: float,
2758+
nft_mint: str,
2759+
) -> Optional[Dict[str, Any]]:
2760+
"""
2761+
List an NFT for sale.
2762+
2763+
Args:
2764+
agent (SolanaAgentKit): The Solana agent instance.
2765+
price (float): The sale price.
2766+
nft_mint (str): The NFT mint address.
2767+
2768+
Returns:
2769+
dict: Transaction details.
2770+
"""
2771+
try:
2772+
from agentipy.tools.use_tensor import TensorManager
2773+
return TensorManager.list_nft_for_sale(self, price, nft_mint)
2774+
except Exception as e:
2775+
raise SolanaAgentKitError(f"Failed to list NFT for sale: {e}")
2776+
2777+
def cancel_listing(
2778+
self,
2779+
nft_mint: str,
2780+
) -> Optional[Dict[str, Any]]:
2781+
"""
2782+
Cancel an NFT listing.
2783+
2784+
Args:
2785+
agent (SolanaAgentKit): The Solana agent instance.
2786+
nft_mint (str): The NFT mint address.
2787+
2788+
Returns:
2789+
dict: Transaction details.
2790+
"""
2791+
try:
2792+
from agentipy.tools.use_tensor import TensorManager
2793+
return TensorManager.cancel_listing(self, nft_mint)
2794+
except Exception as e:
2795+
raise SolanaAgentKitError(f"Failed to cancel listing: {e}")

agentipy/langchain/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from agentipy.langchain.squads import get_squads_tools
3535
from agentipy.langchain.stork import get_stork_tools
3636
from agentipy.langchain.switchboard import get_switchboard_tools
37+
from agentipy.langchain.tensor import get_tensor_tools
3738

3839

3940
def create_solana_tools(solana_kit: SolanaAgentKit):
@@ -77,4 +78,5 @@ def create_solana_tools(solana_kit: SolanaAgentKit):
7778
*get_solutiofi_tools(solana_kit=solana_kit),
7879
*get_squads_tools(solana_kit=solana_kit),
7980
*get_switchboard_tools(solana_kit=solana_kit),
81+
*get_tensor_tools(solana_kit=solana_kit),
8082
]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from agentipy.agent import SolanaAgentKit
2+
from agentipy.langchain.tensor.trade import (TensorCancelListingTool,
3+
TensorListNFTForSaleTool)
4+
5+
6+
def get_tensor_tools(solana_kit: SolanaAgentKit):
7+
return [
8+
TensorCancelListingTool(solana_kit),
9+
TensorListNFTForSaleTool(solana_kit),
10+
]

agentipy/langchain/tensor/trade.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import json
2+
3+
from langchain.tools import BaseTool
4+
5+
from agentipy.agent import SolanaAgentKit
6+
from agentipy.helpers import validate_input
7+
8+
9+
class TensorListNFTForSaleTool(BaseTool):
10+
name: str = "tensor_list_nft_for_sale"
11+
description: str = """
12+
Lists an NFT for sale on Tensor.
13+
14+
Input: A JSON string with:
15+
{
16+
"price": "float, the sale price of the NFT",
17+
"nft_mint": "string, the NFT mint address"
18+
}
19+
20+
Output:
21+
{
22+
"transaction_details": "dict, transaction details",
23+
"message": "string, if an error occurs"
24+
}
25+
"""
26+
solana_kit: SolanaAgentKit
27+
28+
async def _arun(self, input: str):
29+
try:
30+
data = json.loads(input)
31+
schema = {
32+
"price": {"type": float, "required": True},
33+
"nft_mint": {"type": str, "required": True},
34+
}
35+
validate_input(data, schema)
36+
37+
price = data["price"]
38+
nft_mint = data["nft_mint"]
39+
40+
result = await self.solana_kit.list_nft_for_sale(price, nft_mint)
41+
return {
42+
"status": "success",
43+
"transaction_details": result,
44+
}
45+
except Exception as e:
46+
return {
47+
"status": "error",
48+
"message": str(e),
49+
}
50+
51+
def _run(self, input: str):
52+
raise NotImplementedError("This tool only supports async execution via _arun. Please use the async interface.")
53+
54+
55+
class TensorCancelListingTool(BaseTool):
56+
name: str = "tensor_cancel_listing"
57+
description: str = """
58+
Cancels an NFT listing on Tensor.
59+
60+
Input: A JSON string with:
61+
{
62+
"nft_mint": "string, the NFT mint address"
63+
}
64+
65+
Output:
66+
{
67+
"transaction_details": "dict, transaction details",
68+
"message": "string, if an error occurs"
69+
}
70+
"""
71+
solana_kit: SolanaAgentKit
72+
73+
async def _arun(self, input: str):
74+
try:
75+
data = json.loads(input)
76+
schema = {
77+
"nft_mint": {"type": str, "required": True},
78+
}
79+
validate_input(data, schema)
80+
81+
nft_mint = data["nft_mint"]
82+
83+
result = await self.solana_kit.cancel_listing(nft_mint)
84+
return {
85+
"status": "success",
86+
"transaction_details": result,
87+
}
88+
except Exception as e:
89+
return {
90+
"status": "error",
91+
"message": str(e),
92+
}
93+
94+
def _run(self, input: str):
95+
raise NotImplementedError("This tool only supports async execution via _arun. Please use the async interface.")

agentipy/tools/use_tensor.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import logging
2+
from typing import Any, Dict, Optional
3+
4+
import requests
5+
6+
from agentipy.agent import SolanaAgentKit
7+
from agentipy.utils.agentipy_proxy.utils import encrypt_private_key
8+
9+
logger = logging.getLogger(__name__)
10+
11+
12+
class TensorManager:
13+
"""
14+
Manager class to handle Tensor functionalities such as listing NFTs for sale and canceling listings.
15+
"""
16+
17+
@staticmethod
18+
def list_nft_for_sale(
19+
agent: SolanaAgentKit,
20+
price: float,
21+
nft_mint: str,
22+
) -> Optional[Dict[str, Any]]:
23+
"""
24+
Lists an NFT for sale on Tensor.
25+
26+
:param agent: An instance of SolanaAgentKit.
27+
:param price: The listing price of the NFT.
28+
:param nft_mint: The mint address of the NFT.
29+
:return: Transaction signature or error details.
30+
"""
31+
try:
32+
if not price or not nft_mint:
33+
raise ValueError("Price and NFT mint address are required.")
34+
35+
encrypted_private_key = encrypt_private_key(agent.private_key)
36+
37+
payload = {
38+
"requestId": encrypted_private_key["requestId"],
39+
"encrypted_private_key": encrypted_private_key["encryptedPrivateKey"],
40+
"rpc_url": agent.rpc_url,
41+
"open_api_key": agent.openai_api_key,
42+
"price": price,
43+
"nftMint": nft_mint,
44+
}
45+
46+
response = requests.post(
47+
f"{agent.base_proxy_url}/{agent.api_version}/tensor/list-nft-for-sale",
48+
json=payload,
49+
headers={"Content-Type": "application/json"},
50+
)
51+
response.raise_for_status()
52+
53+
data = response.json()
54+
return data if data.get("success") else {"success": False, "error": data.get("error", "Unknown error")}
55+
56+
except requests.exceptions.RequestException as http_error:
57+
logger.error(f"HTTP error during NFT listing: {http_error}", exc_info=True)
58+
return {"success": False, "error": str(http_error)}
59+
except Exception as error:
60+
logger.error(f"Unexpected error during NFT listing: {error}", exc_info=True)
61+
return {"success": False, "error": str(error)}
62+
63+
@staticmethod
64+
def cancel_listing(
65+
agent: SolanaAgentKit,
66+
nft_mint: str,
67+
) -> Optional[Dict[str, Any]]:
68+
"""
69+
Cancels a listed NFT on Tensor.
70+
71+
:param agent: An instance of SolanaAgentKit.
72+
:param nft_mint: The mint address of the NFT to cancel the listing.
73+
:return: Transaction signature or error details.
74+
"""
75+
try:
76+
if not nft_mint:
77+
raise ValueError("NFT mint address is required.")
78+
79+
encrypted_private_key = encrypt_private_key(agent.private_key)
80+
81+
payload = {
82+
"requestId": encrypted_private_key["requestId"],
83+
"encrypted_private_key": encrypted_private_key["encryptedPrivateKey"],
84+
"rpc_url": agent.rpc_url,
85+
"open_api_key": agent.openai_api_key,
86+
"nftMint": nft_mint,
87+
}
88+
89+
response = requests.post(
90+
f"{agent.base_proxy_url}/{agent.api_version}/tensor/cancel-listing",
91+
json=payload,
92+
headers={"Content-Type": "application/json"},
93+
)
94+
response.raise_for_status()
95+
96+
data = response.json()
97+
return data if data.get("success") else {"success": False, "error": data.get("error", "Unknown error")}
98+
99+
except requests.exceptions.RequestException as http_error:
100+
logger.error(f"HTTP error during listing cancellation: {http_error}", exc_info=True)
101+
return {"success": False, "error": str(http_error)}
102+
except Exception as error:
103+
logger.error(f"Unexpected error during listing cancellation: {error}", exc_info=True)
104+
return {"success": False, "error": str(error)}

0 commit comments

Comments
 (0)