acp-plugin-gamesdk 0.1.24__py3-none-any.whl → 0.1.26__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- acp_plugin_gamesdk/acp_plugin.py +194 -202
- acp_plugin_gamesdk/env.py +35 -0
- acp_plugin_gamesdk/interface.py +73 -112
- {acp_plugin_gamesdk-0.1.24.dist-info → acp_plugin_gamesdk-0.1.26.dist-info}/METADATA +4 -14
- acp_plugin_gamesdk-0.1.26.dist-info/RECORD +6 -0
- acp_plugin_gamesdk/acp_client.py +0 -307
- acp_plugin_gamesdk/acp_token.py +0 -352
- acp_plugin_gamesdk/acp_token_abi.py +0 -678
- acp_plugin_gamesdk/configs.py +0 -44
- acp_plugin_gamesdk-0.1.24.dist-info/RECORD +0 -9
- {acp_plugin_gamesdk-0.1.24.dist-info → acp_plugin_gamesdk-0.1.26.dist-info}/WHEEL +0 -0
acp_plugin_gamesdk/interface.py
CHANGED
@@ -1,51 +1,15 @@
|
|
1
|
-
from
|
2
|
-
from
|
3
|
-
from
|
1
|
+
from enum import Enum
|
2
|
+
from typing import Optional, List, Literal, Dict, Any
|
3
|
+
from pydantic import BaseModel
|
4
4
|
|
5
|
+
from virtuals_acp.models import ACPJobPhase
|
5
6
|
|
6
|
-
|
7
|
-
class AcpOffering:
|
7
|
+
class AcpOffering(BaseModel):
|
8
8
|
name: str
|
9
9
|
price: float
|
10
10
|
|
11
11
|
def __str__(self) -> str:
|
12
|
-
|
13
|
-
f"Offering(name={self.name}, price={self.price})"
|
14
|
-
)
|
15
|
-
return output
|
16
|
-
|
17
|
-
|
18
|
-
@dataclass
|
19
|
-
class AcpAgent:
|
20
|
-
id: str
|
21
|
-
name: str
|
22
|
-
twitter_handle: str
|
23
|
-
description: str
|
24
|
-
wallet_address: str
|
25
|
-
offerings: Optional[List[AcpOffering]]
|
26
|
-
|
27
|
-
def __str__(self) -> str:
|
28
|
-
offer = ""
|
29
|
-
if self.offerings:
|
30
|
-
for index, off in enumerate(self.offerings):
|
31
|
-
offer += f"{index + 1}. {str(off)}\n"
|
32
|
-
|
33
|
-
output = (
|
34
|
-
f"😎 Agent ID={self.id}\n"
|
35
|
-
f"Name={self.name}, Description={self.description}, Wallet={self.wallet_address}\n"
|
36
|
-
f"Offerings:\n{offer}"
|
37
|
-
)
|
38
|
-
return output
|
39
|
-
|
40
|
-
|
41
|
-
class AcpJobPhases(IntEnum):
|
42
|
-
REQUEST = 0
|
43
|
-
NEGOTIATION = 1
|
44
|
-
TRANSACTION = 2
|
45
|
-
EVALUATION = 3
|
46
|
-
COMPLETED = 4
|
47
|
-
REJECTED = 5
|
48
|
-
|
12
|
+
return f"Offering(name={self.name}, price={self.price})"
|
49
13
|
|
50
14
|
class AcpJobPhasesDesc(str, Enum):
|
51
15
|
REQUEST = "request"
|
@@ -55,133 +19,130 @@ class AcpJobPhasesDesc(str, Enum):
|
|
55
19
|
COMPLETED = "completed"
|
56
20
|
REJECTED = "rejected"
|
57
21
|
|
58
|
-
|
59
|
-
|
60
|
-
|
22
|
+
ACP_JOB_PHASE_MAP: Dict[ACPJobPhase, AcpJobPhasesDesc] = {
|
23
|
+
ACPJobPhase.REQUEST: AcpJobPhasesDesc.REQUEST,
|
24
|
+
ACPJobPhase.NEGOTIATION: AcpJobPhasesDesc.NEGOTIATION,
|
25
|
+
ACPJobPhase.TRANSACTION: AcpJobPhasesDesc.TRANSACTION,
|
26
|
+
ACPJobPhase.EVALUATION: AcpJobPhasesDesc.EVALUATION,
|
27
|
+
ACPJobPhase.COMPLETED: AcpJobPhasesDesc.COMPLETED,
|
28
|
+
ACPJobPhase.REJECTED: AcpJobPhasesDesc.REJECTED,
|
29
|
+
}
|
30
|
+
|
31
|
+
ACP_JOB_PHASE_REVERSE_MAP: Dict[str, ACPJobPhase] = {
|
32
|
+
"request": ACPJobPhase.REQUEST,
|
33
|
+
"pending_payment": ACPJobPhase.NEGOTIATION,
|
34
|
+
"in_progress": ACPJobPhase.TRANSACTION,
|
35
|
+
"evaluation": ACPJobPhase.EVALUATION,
|
36
|
+
"completed": ACPJobPhase.COMPLETED,
|
37
|
+
"rejected": ACPJobPhase.REJECTED,
|
38
|
+
}
|
39
|
+
|
40
|
+
class AcpRequestMemo(BaseModel):
|
61
41
|
id: int
|
62
|
-
createdAt: int
|
63
42
|
|
64
43
|
def __repr__(self) -> str:
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
@dataclass
|
70
|
-
class ITweet:
|
44
|
+
return f"Memo(ID: {self.id})"
|
45
|
+
|
46
|
+
class ITweet(BaseModel):
|
71
47
|
type: Literal["buyer", "seller"]
|
72
48
|
tweet_id: str
|
73
49
|
content: str
|
74
50
|
created_at: int
|
75
51
|
|
76
|
-
|
77
|
-
@dataclass
|
78
|
-
class AcpJob:
|
52
|
+
class IAcpJob(BaseModel):
|
79
53
|
jobId: Optional[int]
|
80
54
|
clientName: Optional[str]
|
81
55
|
providerName: Optional[str]
|
82
|
-
desc:
|
56
|
+
desc: str
|
83
57
|
price: str
|
84
58
|
providerAddress: Optional[str]
|
85
|
-
clientAddress: Optional[str]
|
86
59
|
phase: AcpJobPhasesDesc
|
87
60
|
memo: List[AcpRequestMemo]
|
88
|
-
tweetHistory: ITweet
|
89
|
-
lastUpdated: int
|
90
|
-
getAgentByWalletAddress: Optional[Callable[[str], AcpAgent]]
|
61
|
+
tweetHistory: Optional[List[Optional[ITweet]]]
|
91
62
|
|
92
63
|
def __repr__(self) -> str:
|
93
|
-
|
64
|
+
return (
|
94
65
|
f"Job ID: {self.jobId}, "
|
95
66
|
f"Client Name: {self.clientName}, "
|
96
67
|
f"Provider Name: {self.providerName}, "
|
97
68
|
f"Description: {self.desc}, "
|
98
69
|
f"Price: {self.price}, "
|
99
70
|
f"Provider Address: {self.providerAddress}, "
|
100
|
-
f"Client Address: {self.clientAddress}, "
|
101
71
|
f"Phase: {self.phase.value}, "
|
102
72
|
f"Memo: {self.memo}, "
|
103
|
-
f"Tweet History: {self.tweetHistory}
|
104
|
-
f"Last Updated: {self.lastUpdated})"
|
73
|
+
f"Tweet History: {self.tweetHistory}"
|
105
74
|
)
|
106
|
-
return output
|
107
|
-
|
108
75
|
|
109
|
-
|
110
|
-
class IDeliverable:
|
76
|
+
class IDeliverable(BaseModel):
|
111
77
|
type: str
|
112
|
-
value:
|
78
|
+
value: str
|
113
79
|
clientName: Optional[str]
|
114
80
|
providerName: Optional[str]
|
115
81
|
|
116
82
|
|
117
|
-
@dataclass
|
118
83
|
class IInventory(IDeliverable):
|
119
84
|
jobId: int
|
120
85
|
clientName: Optional[str]
|
121
86
|
providerName: Optional[str]
|
122
87
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
asABuyer: List[AcpJob]
|
127
|
-
asASeller: List[AcpJob]
|
88
|
+
class AcpJobsSection(BaseModel):
|
89
|
+
asABuyer: List[IAcpJob]
|
90
|
+
asASeller: List[IAcpJob]
|
128
91
|
|
129
92
|
def __str__(self) -> str:
|
130
|
-
buyer_jobs = ""
|
131
|
-
for
|
132
|
-
|
133
|
-
|
134
|
-
seller_jobs = ""
|
135
|
-
for index, job in enumerate(self.asASeller):
|
136
|
-
seller_jobs += f"#{index + 1} {str(job)} \n"
|
137
|
-
|
138
|
-
output = (
|
139
|
-
f"As Buyer:\n{buyer_jobs}\n"
|
140
|
-
f"As Seller:\n{seller_jobs}\n"
|
141
|
-
)
|
142
|
-
return output
|
143
|
-
|
93
|
+
buyer_jobs = "\n".join([f"#{i+1} {str(job)}" for i, job in enumerate(self.asABuyer)])
|
94
|
+
seller_jobs = "\n".join([f"#{i+1} {str(job)}" for i, job in enumerate(self.asASeller)])
|
95
|
+
return f"As Buyer:\n{buyer_jobs}\n\nAs Seller:\n{seller_jobs}"
|
144
96
|
|
145
|
-
|
146
|
-
class AcpJobs:
|
97
|
+
class AcpJobs(BaseModel):
|
147
98
|
active: AcpJobsSection
|
148
|
-
completed: List[
|
149
|
-
cancelled: List[
|
99
|
+
completed: List[IAcpJob]
|
100
|
+
cancelled: List[IAcpJob]
|
150
101
|
|
151
102
|
def __str__(self) -> str:
|
152
|
-
|
103
|
+
return (
|
153
104
|
f"💻 Jobs\n"
|
154
105
|
f"🌕 Active Jobs:\n{self.active}\n"
|
155
106
|
f"🟢 Completed:\n{self.completed}\n"
|
156
|
-
f"🔴 Cancelled:\n{self.cancelled}
|
107
|
+
f"🔴 Cancelled:\n{self.cancelled}"
|
157
108
|
)
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
@dataclass
|
162
|
-
class AcpInventory:
|
109
|
+
|
110
|
+
class AcpInventory(BaseModel):
|
163
111
|
acquired: List[IInventory]
|
164
112
|
produced: Optional[List[IInventory]]
|
165
113
|
|
166
114
|
def __str__(self) -> str:
|
167
|
-
|
115
|
+
return (
|
168
116
|
f"💼 Inventory\n"
|
169
117
|
f"Acquired: {self.acquired}\n"
|
170
|
-
f"Produced: {self.produced}
|
118
|
+
f"Produced: {self.produced}"
|
171
119
|
)
|
172
|
-
return output
|
173
|
-
|
174
120
|
|
175
|
-
|
176
|
-
class AcpState:
|
121
|
+
class AcpState(BaseModel):
|
177
122
|
inventory: AcpInventory
|
178
123
|
jobs: AcpJobs
|
179
124
|
|
180
125
|
def __str__(self) -> str:
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
126
|
+
return (
|
127
|
+
f"🤖 Agent State".center(50, '=') + "\n"
|
128
|
+
f"{str(self.inventory)}\n"
|
129
|
+
f"{str(self.jobs)}\n"
|
130
|
+
f"State End".center(50, '=')
|
186
131
|
)
|
187
|
-
|
132
|
+
|
133
|
+
def to_serializable_dict(obj: Any) -> Any:
|
134
|
+
if isinstance(obj, Enum):
|
135
|
+
return obj.value
|
136
|
+
elif isinstance(obj, dict):
|
137
|
+
return {k: to_serializable_dict(v) for k, v in obj.items()}
|
138
|
+
elif isinstance(obj, list):
|
139
|
+
return [to_serializable_dict(item) for item in obj]
|
140
|
+
elif hasattr(obj, "__dict__"):
|
141
|
+
return {
|
142
|
+
k: to_serializable_dict(v)
|
143
|
+
for k, v in vars(obj).items()
|
144
|
+
if not k.startswith("_")
|
145
|
+
}
|
146
|
+
else:
|
147
|
+
return obj
|
148
|
+
|
@@ -1,30 +1,20 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: acp-plugin-gamesdk
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.26
|
4
4
|
Summary: ACP Plugin for Python SDK for GAME by Virtuals
|
5
5
|
Author: Steven Lee Soon Fatt
|
6
6
|
Author-email: steven@virtuals.io
|
7
|
-
Requires-Python: >=3.
|
7
|
+
Requires-Python: >=3.10,<3.13
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
9
|
-
Classifier: Programming Language :: Python :: 3.9
|
10
9
|
Classifier: Programming Language :: Python :: 3.10
|
11
10
|
Classifier: Programming Language :: Python :: 3.11
|
12
11
|
Classifier: Programming Language :: Python :: 3.12
|
13
|
-
Requires-Dist: aiohttp (>=3.11.14,<4.0.0)
|
14
12
|
Requires-Dist: dacite (>=1.9.2,<2.0.0)
|
15
|
-
Requires-Dist: eth-account (>=0.13.6,<0.14.0)
|
16
|
-
Requires-Dist: eth-typing (>=5.2.0,<6.0.0)
|
17
|
-
Requires-Dist: eth-utils (>=5.2.0,<6.0.0)
|
18
13
|
Requires-Dist: game-sdk (>=0.1.5)
|
19
|
-
Requires-Dist: pydantic (>=2.10.6,<3.0.0)
|
20
14
|
Requires-Dist: python-dotenv (>=1.1.0,<2.0.0)
|
21
|
-
Requires-Dist: python-socketio (>=5.11.1,<6.0.0)
|
22
|
-
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
23
15
|
Requires-Dist: rich (>=13.9.4,<15.0.0)
|
24
|
-
Requires-Dist: twitter-plugin-gamesdk (>=0.2.
|
25
|
-
Requires-Dist: virtuals-
|
26
|
-
Requires-Dist: web3 (>=7.9.0,<8.0.0)
|
27
|
-
Requires-Dist: websocket-client (>=1.7.0,<2.0.0)
|
16
|
+
Requires-Dist: twitter-plugin-gamesdk (>=0.2.10,<0.3.0)
|
17
|
+
Requires-Dist: virtuals-acp (>=0.1.13)
|
28
18
|
Description-Content-Type: text/markdown
|
29
19
|
|
30
20
|
# ACP Plugin
|
@@ -0,0 +1,6 @@
|
|
1
|
+
acp_plugin_gamesdk/acp_plugin.py,sha256=0mh1lFLIm-BN9mlHQif1yIpyNfB7J1_KZpu7OV4vLW4,26673
|
2
|
+
acp_plugin_gamesdk/env.py,sha256=_1UQtONrfC9hkO2yGYfxawEk71nF_0GXC_79a0RVyv0,1367
|
3
|
+
acp_plugin_gamesdk/interface.py,sha256=4IdKjTJMH8Rmoz55Jv0vCgdu4wqgw3wqqK1C8JBHldM,4262
|
4
|
+
acp_plugin_gamesdk-0.1.26.dist-info/METADATA,sha256=qWf864Ss4sNNBH4m26QXQj2flZTwo6N7OLUmIb0jotE,12345
|
5
|
+
acp_plugin_gamesdk-0.1.26.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
6
|
+
acp_plugin_gamesdk-0.1.26.dist-info/RECORD,,
|
acp_plugin_gamesdk/acp_client.py
DELETED
@@ -1,307 +0,0 @@
|
|
1
|
-
import time
|
2
|
-
import traceback
|
3
|
-
from datetime import datetime, timezone
|
4
|
-
from typing import List, Optional
|
5
|
-
|
6
|
-
import requests
|
7
|
-
from dacite import Config, from_dict
|
8
|
-
from web3 import Web3
|
9
|
-
|
10
|
-
from acp_plugin_gamesdk.acp_token import AcpToken, MemoType
|
11
|
-
from acp_plugin_gamesdk.interface import (
|
12
|
-
AcpAgent,
|
13
|
-
AcpJobPhases,
|
14
|
-
AcpJobPhasesDesc,
|
15
|
-
AcpOffering,
|
16
|
-
AcpState,
|
17
|
-
)
|
18
|
-
|
19
|
-
|
20
|
-
class AcpClient:
|
21
|
-
def __init__(self, api_key: str, acp_token: AcpToken):
|
22
|
-
self.api_key = api_key
|
23
|
-
self.acp_token = acp_token
|
24
|
-
self.web3 = Web3()
|
25
|
-
|
26
|
-
self.acp_base_url = self.acp_token.acp_base_url
|
27
|
-
self.base_url = self.acp_token.game_api_url + "/acp"
|
28
|
-
|
29
|
-
@property
|
30
|
-
def agent_wallet_address(self) -> str:
|
31
|
-
return self.acp_token.get_agent_wallet_address()
|
32
|
-
|
33
|
-
def get_state(self) -> AcpState:
|
34
|
-
response = requests.get(
|
35
|
-
f"{self.base_url}/states/{self.agent_wallet_address}",
|
36
|
-
headers={"x-api-key": self.api_key}
|
37
|
-
)
|
38
|
-
payload = response.json()
|
39
|
-
result = from_dict(data_class=AcpState, data=payload,
|
40
|
-
config=Config(type_hooks={AcpJobPhasesDesc: AcpJobPhasesDesc}))
|
41
|
-
return result
|
42
|
-
|
43
|
-
def browse_agents(
|
44
|
-
self,
|
45
|
-
cluster: Optional[str] = None,
|
46
|
-
query: Optional[str] = None,
|
47
|
-
rerank: Optional[bool] = True,
|
48
|
-
top_k: Optional[int] = 1,
|
49
|
-
) -> List[AcpAgent]:
|
50
|
-
|
51
|
-
url = f"{self.acp_base_url}/agents"
|
52
|
-
|
53
|
-
params = {
|
54
|
-
"search": query,
|
55
|
-
"filters[cluster]": cluster,
|
56
|
-
"filters[walletAddress][$notIn]": self.agent_wallet_address,
|
57
|
-
"rerank": "true" if rerank else "false",
|
58
|
-
"top_k": top_k,
|
59
|
-
}
|
60
|
-
response = requests.get(url, params=params)
|
61
|
-
|
62
|
-
if response.status_code != 200:
|
63
|
-
raise Exception(
|
64
|
-
f"Error occured in browse_agents function. Failed to browse agents.\n"
|
65
|
-
f"Response status code: {response.status_code}\n"
|
66
|
-
f"Response description: {response.text}\n"
|
67
|
-
)
|
68
|
-
|
69
|
-
response_json = response.json()
|
70
|
-
|
71
|
-
result = []
|
72
|
-
|
73
|
-
for agent in response_json.get("data", []):
|
74
|
-
if agent["offerings"]:
|
75
|
-
offerings = [AcpOffering(name=offering["name"], price=offering["price"]) for offering in
|
76
|
-
agent["offerings"]]
|
77
|
-
else:
|
78
|
-
offerings = None
|
79
|
-
|
80
|
-
result.append(
|
81
|
-
AcpAgent(
|
82
|
-
id=agent["id"],
|
83
|
-
name=agent["name"],
|
84
|
-
twitter_handle=agent["twitterHandle"],
|
85
|
-
description=agent["description"],
|
86
|
-
wallet_address=agent["walletAddress"],
|
87
|
-
offerings=offerings,
|
88
|
-
)
|
89
|
-
)
|
90
|
-
|
91
|
-
return result
|
92
|
-
|
93
|
-
def create_job(
|
94
|
-
self,
|
95
|
-
provider_address: str,
|
96
|
-
price: float,
|
97
|
-
job_description: str,
|
98
|
-
evaluator_address: str,
|
99
|
-
expired_at: datetime,
|
100
|
-
) -> int:
|
101
|
-
tx_result = self.acp_token.create_job(
|
102
|
-
provider_address=provider_address,
|
103
|
-
evaluator_address=evaluator_address,
|
104
|
-
expire_at=expired_at
|
105
|
-
)
|
106
|
-
|
107
|
-
job_id = None
|
108
|
-
retry_count = 3
|
109
|
-
retry_delay = 3
|
110
|
-
|
111
|
-
time.sleep(retry_delay)
|
112
|
-
for attempt in range(retry_count):
|
113
|
-
try:
|
114
|
-
response = self.acp_token.validate_transaction(tx_result["txHash"])
|
115
|
-
data = response.get("data", {})
|
116
|
-
if not data:
|
117
|
-
raise Exception("Invalid tx_hash!")
|
118
|
-
|
119
|
-
if data.get("status") == "retry":
|
120
|
-
raise Exception("Transaction failed, retrying...")
|
121
|
-
|
122
|
-
if data.get("status") == "failed":
|
123
|
-
break
|
124
|
-
|
125
|
-
if data.get("status") == "success":
|
126
|
-
job_id = int(data.get("result").get("jobId"))
|
127
|
-
|
128
|
-
if job_id is not None and job_id != "":
|
129
|
-
break
|
130
|
-
|
131
|
-
except Exception as e:
|
132
|
-
print(f"Error in create_job function: {e}")
|
133
|
-
print(traceback.format_exc())
|
134
|
-
if attempt < retry_count - 1:
|
135
|
-
time.sleep(retry_delay)
|
136
|
-
else:
|
137
|
-
raise
|
138
|
-
|
139
|
-
if job_id is None or job_id == "":
|
140
|
-
raise Exception("Failed to create job")
|
141
|
-
|
142
|
-
self.acp_token.create_memo(
|
143
|
-
job_id=job_id,
|
144
|
-
content=job_description,
|
145
|
-
memo_type=MemoType.MESSAGE,
|
146
|
-
is_secured=False,
|
147
|
-
next_phase=AcpJobPhases.NEGOTIATION
|
148
|
-
)
|
149
|
-
|
150
|
-
payload = {
|
151
|
-
"jobId": job_id,
|
152
|
-
"clientAddress": self.agent_wallet_address,
|
153
|
-
"providerAddress": provider_address,
|
154
|
-
"description": job_description,
|
155
|
-
"price": price,
|
156
|
-
"expiredAt": expired_at.astimezone(timezone.utc).isoformat(),
|
157
|
-
"evaluatorAddress": evaluator_address
|
158
|
-
}
|
159
|
-
|
160
|
-
requests.post(
|
161
|
-
self.base_url,
|
162
|
-
json=payload,
|
163
|
-
headers={
|
164
|
-
"Accept": "application/json",
|
165
|
-
"Content-Type": "application/json",
|
166
|
-
"x-api-key": self.api_key
|
167
|
-
}
|
168
|
-
)
|
169
|
-
|
170
|
-
return job_id
|
171
|
-
|
172
|
-
def response_job(self, job_id: int, accept: bool, memo_id: int, reasoning: str):
|
173
|
-
if accept:
|
174
|
-
self.acp_token.sign_memo(memo_id, accept, reasoning)
|
175
|
-
time.sleep(5)
|
176
|
-
|
177
|
-
return self.acp_token.create_memo(
|
178
|
-
job_id=job_id,
|
179
|
-
content=f"Job {job_id} accepted. {reasoning}",
|
180
|
-
memo_type=MemoType.MESSAGE,
|
181
|
-
is_secured=False,
|
182
|
-
next_phase=AcpJobPhases.TRANSACTION
|
183
|
-
)
|
184
|
-
else:
|
185
|
-
return self.acp_token.create_memo(
|
186
|
-
job_id=job_id,
|
187
|
-
content=f"Job {job_id} rejected. {reasoning}",
|
188
|
-
memo_type=MemoType.MESSAGE,
|
189
|
-
is_secured=False,
|
190
|
-
next_phase=AcpJobPhases.REJECTED
|
191
|
-
)
|
192
|
-
|
193
|
-
def make_payment(self, job_id: int, amount: float, memo_id: int, reason: str):
|
194
|
-
# Convert amount to Wei (smallest ETH unit)
|
195
|
-
amount_wei = self.web3.to_wei(amount, 'ether')
|
196
|
-
|
197
|
-
self.acp_token.set_budget(job_id, amount_wei)
|
198
|
-
time.sleep(5)
|
199
|
-
self.acp_token.approve_allowance(amount_wei)
|
200
|
-
time.sleep(5)
|
201
|
-
self.acp_token.sign_memo(memo_id, True, reason)
|
202
|
-
time.sleep(5)
|
203
|
-
return self.acp_token.create_memo(
|
204
|
-
job_id=job_id,
|
205
|
-
content=f"Payment of {amount} made {reason}",
|
206
|
-
memo_type=MemoType.MESSAGE,
|
207
|
-
is_secured=False,
|
208
|
-
next_phase=AcpJobPhases.EVALUATION
|
209
|
-
)
|
210
|
-
|
211
|
-
def deliver_job(self, job_id: int, deliverable: str):
|
212
|
-
return self.acp_token.create_memo(
|
213
|
-
job_id=job_id,
|
214
|
-
content=deliverable,
|
215
|
-
memo_type=MemoType.MESSAGE,
|
216
|
-
is_secured=False,
|
217
|
-
next_phase=AcpJobPhases.COMPLETED
|
218
|
-
)
|
219
|
-
|
220
|
-
def add_tweet(self, job_id: int, tweet_id: str, content: str):
|
221
|
-
payload = {
|
222
|
-
"tweetId": tweet_id,
|
223
|
-
"content": content
|
224
|
-
}
|
225
|
-
|
226
|
-
response = requests.post(
|
227
|
-
f"{self.base_url}/{job_id}/tweets/{self.agent_wallet_address}",
|
228
|
-
json=payload,
|
229
|
-
headers={
|
230
|
-
"Accept": "application/json",
|
231
|
-
"Content-Type": "application/json",
|
232
|
-
"x-api-key": self.api_key
|
233
|
-
}
|
234
|
-
)
|
235
|
-
|
236
|
-
if response.status_code != 200 and response.status_code != 201:
|
237
|
-
raise Exception(
|
238
|
-
f"Error occured in add_tweet function. Failed to add tweet.\n"
|
239
|
-
f"Response status code: {response.status_code}\n"
|
240
|
-
f"Response description: {response.text}\n"
|
241
|
-
)
|
242
|
-
|
243
|
-
return response.json()
|
244
|
-
|
245
|
-
def reset_state(self) -> None:
|
246
|
-
response = requests.delete(
|
247
|
-
f"{self.base_url}/states/{self.agent_wallet_address}",
|
248
|
-
headers={"x-api-key": self.api_key}
|
249
|
-
)
|
250
|
-
|
251
|
-
if response.status_code not in [200, 204]:
|
252
|
-
raise Exception(
|
253
|
-
f"Error occured in reset_state function. Failed to reset state\n"
|
254
|
-
f"Response status code: {response.status_code}\n"
|
255
|
-
f"Response description: {response.text}\n"
|
256
|
-
)
|
257
|
-
|
258
|
-
def delete_completed_job(self, job_id: int) -> None:
|
259
|
-
response = requests.delete(
|
260
|
-
f"{self.base_url}/{job_id}/wallet/{self.agent_wallet_address}",
|
261
|
-
headers={"x-api-key": self.api_key}
|
262
|
-
)
|
263
|
-
|
264
|
-
if response.status_code not in [200, 204]:
|
265
|
-
raise Exception(
|
266
|
-
f"Error occurred in delete_completed_job function. Failed to delete job.\n"
|
267
|
-
f"Response status code: {response.status_code}\n"
|
268
|
-
f"Response description: {response.text}\n"
|
269
|
-
)
|
270
|
-
|
271
|
-
def get_agent_by_wallet_address(self, wallet_address: str) -> Optional[AcpAgent]:
|
272
|
-
url = f"{self.acp_base_url}/agents?filters[walletAddress]={wallet_address}"
|
273
|
-
|
274
|
-
response = requests.get(
|
275
|
-
url,
|
276
|
-
)
|
277
|
-
|
278
|
-
if response.status_code != 200:
|
279
|
-
raise Exception(
|
280
|
-
f"Failed to get agent: {response.status_code} {response.text}"
|
281
|
-
)
|
282
|
-
|
283
|
-
response_json = response.json()
|
284
|
-
|
285
|
-
result = []
|
286
|
-
|
287
|
-
if len(response_json.get("data", [])) == 0:
|
288
|
-
return None
|
289
|
-
|
290
|
-
for agent in response_json.get("data", []):
|
291
|
-
if agent["offerings"]:
|
292
|
-
offerings = [AcpOffering(name=offering["name"], price=offering["price"]) for offering in
|
293
|
-
agent["offerings"]]
|
294
|
-
else:
|
295
|
-
offerings = None
|
296
|
-
|
297
|
-
result.append(
|
298
|
-
AcpAgent(
|
299
|
-
id=agent["id"],
|
300
|
-
name=agent["name"],
|
301
|
-
twitter_handle=agent["twitterHandle"],
|
302
|
-
description=agent["description"],
|
303
|
-
wallet_address=agent["walletAddress"],
|
304
|
-
offerings=offerings,
|
305
|
-
)
|
306
|
-
)
|
307
|
-
return result[0]
|