1
- import os
2
- import time
3
1
import json
2
+ import time
4
3
from typing import List
4
+
5
5
from dotenv import load_dotenv
6
6
7
7
from virtuals_acp import VirtualsACP , ACPJob , ACPJobPhase
8
- from virtuals_acp .configs import BASE_SEPOLIA_CONFIG
8
+ from virtuals_acp .env import EnvSettings
9
9
10
10
load_dotenv (override = True )
11
11
12
- SELLER_PRIVATE_KEY = os . environ . get ( "WHITELISTED_WALLET_PRIVATE_KEY" )
13
- SELLER_WALLET_ADDRESS = os . environ . get ( "SELLER_AGENT_WALLET_ADDRESS" )
12
+ # --- Configuration for the job polling interval ---
13
+ POLL_INTERVAL_SECONDS = 20
14
14
15
- if not all ([SELLER_PRIVATE_KEY , SELLER_WALLET_ADDRESS ]):
16
- print ("Error: Ensure SELLER_PRIVATE_KEY and SELLER_WALLET_ADDRESS are set." )
17
- exit (1 )
18
15
19
- DELIVERABLE_CONTENT = {
20
- "type" : "url" ,
21
- "value" : "https://virtuals.io/delivered_meme.png" ,
22
- "notes" : "Your meme is ready!"
23
- }
16
+ # --------------------------------------------------
24
17
25
- POLL_INTERVAL_SECONDS = 20
18
+ def seller ():
19
+ env = EnvSettings ()
26
20
27
- def main ():
28
- print ("--- Seller Script ---" )
29
- seller_acp = VirtualsACP (
30
- wallet_private_key = SELLER_PRIVATE_KEY ,
31
- agent_wallet_address = SELLER_WALLET_ADDRESS ,
32
- config = BASE_SEPOLIA_CONFIG
21
+ acp = VirtualsACP (
22
+ wallet_private_key = env .WHITELISTED_WALLET_PRIVATE_KEY ,
23
+ agent_wallet_address = env .SELLER_AGENT_WALLET_ADDRESS ,
24
+ entity_id = env .SELLER_ENTITY_ID ,
33
25
)
34
- print (f"Seller ACP Initialized. Agent: { seller_acp .agent_address } " )
26
+ print (f"Seller ACP Initialized. Agent: { acp .agent_address } " )
35
27
36
28
# Keep track of jobs to avoid reprocessing in this simple loop
37
29
# job_id: {"responded_to_request": bool, "delivered_work": bool}
38
30
processed_job_stages = {}
39
31
40
32
while True :
41
- print (f"\n Seller: Polling for active jobs for { SELLER_WALLET_ADDRESS } ..." )
42
- active_jobs_list : List [ACPJob ] = seller_acp .get_active_jobs ()
33
+ print (f"\n Seller: Polling for active jobs for { env . SELLER_AGENT_WALLET_ADDRESS } ..." )
34
+ active_jobs_list : List [ACPJob ] = acp .get_active_jobs ()
43
35
44
36
if not active_jobs_list :
45
37
print ("Seller: No active jobs found in this poll." )
46
38
time .sleep (POLL_INTERVAL_SECONDS )
47
39
continue
48
-
49
- for job_summary in active_jobs_list :
50
- onchain_job_id = job_summary .id
40
+
41
+ for job in active_jobs_list :
42
+ onchain_job_id = job .id
51
43
52
44
# Ensure this job is for the current seller
53
- if job_summary .provider_address != seller_acp .agent_address :
45
+ if job .provider_address != acp .agent_address :
54
46
continue
55
47
56
48
job_stages = processed_job_stages .get (onchain_job_id , {})
57
49
58
50
try :
59
51
# Fetch full details to get current phase and memos
60
- job_details = seller_acp .get_job_by_onchain_id (onchain_job_id )
52
+ job_details = acp .get_job_by_onchain_id (onchain_job_id )
61
53
current_phase = job_details .phase
62
54
print (f"Seller: Checking job { onchain_job_id } . Current Phase: { current_phase .name } " )
63
55
@@ -69,20 +61,21 @@ def main():
69
61
if ACPJobPhase (memo .next_phase ) == ACPJobPhase .NEGOTIATION :
70
62
buyers_initial_memo_to_sign = memo
71
63
break
72
-
64
+
73
65
if buyers_initial_memo_to_sign :
74
- print (f"Seller: Job { onchain_job_id } is in REQUEST. Responding to buyer's memo { buyers_initial_memo_to_sign .id } ..." )
75
- seller_acp .respond_to_job_memo (
66
+ print (
67
+ f"Seller: Job { onchain_job_id } is in REQUEST. Responding to buyer's memo { buyers_initial_memo_to_sign .id } ..." )
68
+ acp .respond_to_job_memo (
76
69
job_id = onchain_job_id ,
77
- memo_id = buyers_initial_memo_to_sign .id , # ID of the memo created by Buyer
70
+ memo_id = buyers_initial_memo_to_sign .id , # ID of the memo created by Buyer
78
71
accept = True ,
79
72
reason = "Seller accepts the job offer."
80
73
)
81
74
print (f"Seller: Accepted job { onchain_job_id } . Job phase should move to NEGOTIATION." )
82
75
job_stages ["responded_to_request" ] = True
83
76
else :
84
77
print (f"Seller: Job { onchain_job_id } in REQUEST, but could not find buyer's initial memo." )
85
-
78
+
86
79
# 2. Submit Deliverable (if job is paid and not yet delivered)
87
80
elif current_phase == ACPJobPhase .TRANSACTION and not job_stages .get ("delivered_work" ):
88
81
# Buyer has paid, job is in TRANSACTION. Seller needs to deliver.
@@ -92,30 +85,35 @@ def main():
92
85
if ACPJobPhase (memo .next_phase ) == ACPJobPhase .EVALUATION :
93
86
buyers_payment_confirmation_memo = memo
94
87
break
95
-
88
+
96
89
if buyers_payment_confirmation_memo :
97
90
print (f"Seller: Job { onchain_job_id } is PAID (TRANSACTION phase). Submitting deliverable..." )
98
- seller_acp .submit_job_deliverable (
91
+ acp .submit_job_deliverable (
99
92
job_id = onchain_job_id ,
100
- deliverable_content = json .dumps (DELIVERABLE_CONTENT )
93
+ deliverable_content = json .dumps ({
94
+ "type" : "url" ,
95
+ "value" : "https://example.com"
96
+ })
101
97
)
102
98
print (f"Seller: Deliverable submitted for job { onchain_job_id } . Job should move to EVALUATION." )
103
99
job_stages ["delivered_work" ] = True
104
100
else :
105
- print (f"Seller: Job { onchain_job_id } in TRANSACTION, but couldn't find buyer's payment memo to confirm." )
101
+ print (
102
+ f"Seller: Job { onchain_job_id } in TRANSACTION, but couldn't find buyer's payment memo to confirm." )
106
103
107
104
elif current_phase in [ACPJobPhase .EVALUATION , ACPJobPhase .COMPLETED , ACPJobPhase .REJECTED ]:
108
105
print (f"Seller: Job { onchain_job_id } is in { current_phase .name } . No further action for seller." )
109
106
# Mark as fully handled for this script
110
107
job_stages ["responded_to_request" ] = True
111
108
job_stages ["delivered_work" ] = True
112
-
109
+
113
110
processed_job_stages [onchain_job_id ] = job_stages
114
111
115
112
except Exception as e :
116
113
print (f"Seller: Error processing job { onchain_job_id } : { e } " )
117
-
114
+
118
115
time .sleep (POLL_INTERVAL_SECONDS )
119
116
117
+
120
118
if __name__ == "__main__" :
121
- main ()
119
+ seller ()
0 commit comments