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.
@@ -1,352 +0,0 @@
1
- from datetime import datetime
2
- from enum import IntEnum
3
- import json
4
- import time
5
- import traceback
6
- from typing import Optional, Tuple, TypedDict
7
-
8
- from eth_account import Account
9
- from eth_account.messages import encode_defunct
10
- import requests
11
- from web3 import Web3
12
-
13
- from acp_plugin_gamesdk.acp_token_abi import ACP_TOKEN_ABI
14
- from acp_plugin_gamesdk.configs import ACPContractConfig
15
-
16
-
17
- class MemoType(IntEnum):
18
- MESSAGE = 0
19
- CONTEXT_URL = 1
20
- IMAGE_URL = 2
21
- VOICE_URL = 3
22
- OBJECT_URL = 4
23
- TXHASH = 5
24
-
25
-
26
- class IMemo(TypedDict):
27
- content: str
28
- memoType: MemoType
29
- isSecured: bool
30
- nextPhase: int
31
- jobId: int
32
- numApprovals: int
33
- sender: str
34
-
35
-
36
- class IJob(TypedDict):
37
- id: int
38
- client: str
39
- provider: str
40
- budget: int
41
- amountClaimed: int
42
- phase: int
43
- memoCount: int
44
- expiredAt: int
45
- evaluatorCount: int
46
-
47
-
48
- JobResult = Tuple[int, str, str, str, str, str, str, str, int]
49
-
50
-
51
- class AcpToken:
52
- def __init__(
53
- self,
54
- wallet_private_key: str,
55
- agent_wallet_address: str,
56
- config: ACPContractConfig,
57
- ):
58
- self.web3 = Web3(Web3.HTTPProvider(config.rpc_url))
59
- self.account = Account.from_key(wallet_private_key)
60
- self.agent_wallet_address = agent_wallet_address
61
- self.contract_address = Web3.to_checksum_address(config.contract_address)
62
- self.virtuals_token_address = Web3.to_checksum_address(config.virtuals_token_address)
63
- self.contract = self.web3.eth.contract(
64
- address=self.contract_address,
65
- abi=ACP_TOKEN_ABI
66
- )
67
- self.virtuals_token_contract = self.web3.eth.contract(
68
- address=self.virtuals_token_address,
69
- abi=[{
70
- "inputs": [
71
- {
72
- "internalType": "address",
73
- "name": "spender",
74
- "type": "address"
75
- },
76
- {
77
- "internalType": "uint256",
78
- "name": "amount",
79
- "type": "uint256"
80
- }
81
- ],
82
- "name": "approve",
83
- "outputs": [
84
- {
85
- "internalType": "bool",
86
- "name": "",
87
- "type": "bool"
88
- }
89
- ],
90
- "stateMutability": "nonpayable",
91
- "type": "function"
92
- }]
93
- )
94
- self.acp_base_url = config.acp_api_url
95
- self.game_api_url = config.game_api_url
96
-
97
- def get_agent_wallet_address(self) -> str:
98
- return self.agent_wallet_address
99
-
100
- def get_contract_address(self) -> str:
101
- return self.contract_address
102
-
103
- def validate_transaction(self, hash_value: str) -> object:
104
- try:
105
- response = requests.post(f"{self.acp_base_url}/acp-agent-wallets/trx-result",
106
- json={"userOpHash": hash_value})
107
- return response.json()
108
- except Exception as error:
109
- print(traceback.format_exc())
110
- raise Exception(f"Failed to get job_id {error}")
111
-
112
- def create_job(
113
- self,
114
- provider_address: str,
115
- evaluator_address: str,
116
- expire_at: datetime
117
- ) -> dict:
118
- try:
119
- provider_address = Web3.to_checksum_address(provider_address)
120
- evaluator_address = Web3.to_checksum_address(evaluator_address)
121
- expire_timestamp = int(expire_at.timestamp())
122
-
123
- # Sign the transaction
124
- trx_data, signature = self._sign_transaction(
125
- "createJob",
126
- [provider_address, evaluator_address, expire_timestamp]
127
- )
128
-
129
- # Prepare payload
130
- payload = {
131
- "agentWallet": self.get_agent_wallet_address(),
132
- "trxData": trx_data,
133
- "signature": signature
134
- }
135
-
136
- # Submit to custom API
137
- api_url = f"{self.acp_base_url}/acp-agent-wallets/transactions"
138
- response = requests.post(api_url, json=payload)
139
-
140
- if response.json().get("error"):
141
- raise Exception(
142
- f"Failed to create job {response.json().get('error').get('status')}, Message: {response.json().get('error').get('message')}")
143
-
144
- # Return transaction hash or response ID
145
- return {"txHash": response.json().get("data", {}).get("userOpHash", "")}
146
-
147
- except Exception as e:
148
- raise
149
-
150
- def approve_allowance(self, price_in_wei: int) -> str:
151
- try:
152
- trx_data, signature = self._sign_transaction(
153
- "approve",
154
- [self.contract_address, price_in_wei],
155
- self.virtuals_token_address
156
- )
157
-
158
- payload = {
159
- "agentWallet": self.get_agent_wallet_address(),
160
- "trxData": trx_data,
161
- "signature": signature
162
- }
163
-
164
- api_url = f"{self.acp_base_url}/acp-agent-wallets/transactions"
165
- response = requests.post(api_url, json=payload)
166
-
167
- if (response.json().get("error")):
168
- raise Exception(
169
- f"Failed to approve allowance {response.json().get('error').get('status')}, Message: {response.json().get('error').get('message')}")
170
-
171
- return response.json()
172
- except Exception as e:
173
- print(f"An error occurred while approving allowance: {e}")
174
- raise
175
-
176
- def create_memo(
177
- self,
178
- job_id: int,
179
- content: str,
180
- memo_type: MemoType,
181
- is_secured: bool,
182
- next_phase: int
183
- ) -> dict:
184
- retries = 3
185
- error = None
186
- while retries > 0:
187
- try:
188
- trx_data, signature = self._sign_transaction(
189
- "createMemo",
190
- [job_id, content, memo_type, is_secured, next_phase]
191
- )
192
-
193
- payload = {
194
- "agentWallet": self.get_agent_wallet_address(),
195
- "trxData": trx_data,
196
- "signature": signature
197
- }
198
-
199
- api_url = f"{self.acp_base_url}/acp-agent-wallets/transactions"
200
- response = requests.post(api_url, json=payload)
201
-
202
- if (response.json().get("error")):
203
- raise Exception(
204
- f"Failed to create memo {response.json().get('error').get('status')}, Message: {response.json().get('error').get('message')}")
205
-
206
- return {"txHash": response.json().get("txHash", response.json().get("id", "")),
207
- "memoId": response.json().get("memoId", "")}
208
- except Exception as e:
209
- print(f"{e}")
210
- print(traceback.format_exc())
211
- error = e
212
- retries -= 1
213
- time.sleep(2 * (3 - retries))
214
-
215
- if error:
216
- raise Exception(f"{error}")
217
-
218
- def _sign_transaction(self, method_name: str, args: list, contract_address: Optional[str] = None) -> Tuple[
219
- dict, str]:
220
- if contract_address:
221
- encoded_data = self.virtuals_token_contract.encode_abi(method_name, args=args)
222
- else:
223
- encoded_data = self.contract.encode_abi(method_name, args=args)
224
-
225
- trx_data = {
226
- "target": contract_address if contract_address else self.get_contract_address(),
227
- "value": "0",
228
- "data": encoded_data
229
- }
230
-
231
- message_json = json.dumps(trx_data, separators=(",", ":"), sort_keys=False)
232
- message_bytes = message_json.encode()
233
-
234
- # Sign the transaction
235
- message = encode_defunct(message_bytes)
236
- signature = "0x" + self.account.sign_message(message).signature.hex()
237
-
238
- return trx_data, signature
239
-
240
- def sign_memo(
241
- self,
242
- memo_id: int,
243
- is_approved: bool,
244
- reason: Optional[str] = ""
245
- ) -> str:
246
- retries = 3
247
- error = None
248
- while retries > 0:
249
- try:
250
- trx_data, signature = self._sign_transaction(
251
- "signMemo",
252
- [memo_id, is_approved, reason]
253
- )
254
-
255
- payload = {
256
- "agentWallet": self.get_agent_wallet_address(),
257
- "trxData": trx_data,
258
- "signature": signature
259
- }
260
-
261
- api_url = f"{self.acp_base_url}/acp-agent-wallets/transactions"
262
- response = requests.post(api_url, json=payload)
263
-
264
- if (response.json().get("error")):
265
- raise Exception(
266
- f"Failed to sign memo {response.json().get('error').get('status')}, Message: {response.json().get('error').get('message')}")
267
-
268
- return response.json()
269
-
270
- except Exception as e:
271
- error = e
272
- print(f"{error}")
273
- print(traceback.format_exc())
274
- retries -= 1
275
- time.sleep(2 * (3 - retries))
276
-
277
- raise Exception(f"Failed to sign memo {error}")
278
-
279
- def set_budget(self, job_id: int, budget: int) -> str:
280
- try:
281
- trx_data, signature = self._sign_transaction(
282
- "setBudget",
283
- [job_id, budget]
284
- )
285
-
286
- payload = {
287
- "agentWallet": self.get_agent_wallet_address(),
288
- "trxData": trx_data,
289
- "signature": signature
290
- }
291
-
292
- api_url = f"{self.acp_base_url}/acp-agent-wallets/transactions"
293
- response = requests.post(api_url, json=payload)
294
-
295
- if (response.json().get("error")):
296
- raise Exception(
297
- f"Failed to set budget {response.json().get('error').get('status')}, Message: {response.json().get('error').get('message')}")
298
-
299
- return response.json()
300
- except Exception as error:
301
- raise Exception(f"{error}")
302
-
303
- def get_job(self, job_id: int) -> Optional[IJob]:
304
- try:
305
- job_data = self.contract.functions.jobs(job_id).call()
306
-
307
- if not job_data:
308
- return None
309
-
310
- return {
311
- 'id': job_data[0],
312
- 'client': job_data[1],
313
- 'provider': job_data[2],
314
- 'budget': int(job_data[3]),
315
- 'amountClaimed': int(job_data[4]),
316
- 'phase': int(job_data[5]),
317
- 'memoCount': int(job_data[6]),
318
- 'expiredAt': int(job_data[7]),
319
- 'evaluatorCount': int(job_data[8])
320
- }
321
- except Exception as error:
322
- raise Exception(f"{error}")
323
-
324
- def get_memo_by_job(
325
- self,
326
- job_id: int,
327
- memo_type: Optional[MemoType] = None
328
- ) -> Optional[IMemo]:
329
- try:
330
- memos = self.contract.functions.getAllMemos(job_id).call()
331
-
332
- if memo_type is not None:
333
- filtered_memos = [m for m in memos if m['memoType'] == memo_type]
334
- return filtered_memos[-1] if filtered_memos else None
335
- else:
336
- return memos[-1] if memos else None
337
- except Exception as error:
338
- raise Exception(f"Failed to get memo by job {error}")
339
-
340
- def get_memos_for_phase(
341
- self,
342
- job_id: int,
343
- phase: int,
344
- target_phase: int
345
- ) -> Optional[IMemo]:
346
- try:
347
- memos = self.contract.functions.getMemosForPhase(job_id, phase).call()
348
-
349
- target_memos = [m for m in memos if m['nextPhase'] == target_phase]
350
- return target_memos[-1] if target_memos else None
351
- except Exception as error:
352
- raise Exception(f"Failed to get memos for phase {error}")