genlayer-test 0.7.0__py3-none-any.whl → 0.9.0__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.
Files changed (58) hide show
  1. {genlayer_test-0.7.0.dist-info → genlayer_test-0.9.0.dist-info}/METADATA +245 -4
  2. genlayer_test-0.9.0.dist-info/RECORD +38 -0
  3. {genlayer_test-0.7.0.dist-info → genlayer_test-0.9.0.dist-info}/top_level.txt +0 -1
  4. gltest/__init__.py +3 -0
  5. gltest/types.py +12 -1
  6. gltest/validators/__init__.py +3 -0
  7. gltest/validators/validator_factory.py +136 -0
  8. gltest_cli/config/constants.py +7 -0
  9. gltest_cli/config/plugin.py +22 -4
  10. gltest_cli/config/types.py +81 -46
  11. gltest_cli/config/user.py +95 -7
  12. genlayer_test-0.7.0.dist-info/RECORD +0 -79
  13. tests/__init__.py +0 -0
  14. tests/conftest.py +0 -1
  15. tests/examples/contracts/football_prediction_market.py +0 -100
  16. tests/examples/contracts/intelligent_oracle.py +0 -370
  17. tests/examples/contracts/intelligent_oracle_factory.py +0 -49
  18. tests/examples/contracts/invalid_deploy.py +0 -10
  19. tests/examples/contracts/llm_erc20.py +0 -70
  20. tests/examples/contracts/log_indexer.py +0 -69
  21. tests/examples/contracts/multi_file_contract/__init__.py +0 -24
  22. tests/examples/contracts/multi_file_contract/other.py +0 -14
  23. tests/examples/contracts/multi_read_erc20.py +0 -29
  24. tests/examples/contracts/multi_tenant_storage.py +0 -51
  25. tests/examples/contracts/read_erc20.py +0 -19
  26. tests/examples/contracts/simple_time_contract.py +0 -85
  27. tests/examples/contracts/storage.py +0 -23
  28. tests/examples/contracts/user_storage.py +0 -25
  29. tests/examples/contracts/wizard_of_coin.py +0 -57
  30. tests/examples/tests/test_football_prediction_market.py +0 -38
  31. tests/examples/tests/test_intelligent_oracle_factory.py +0 -162
  32. tests/examples/tests/test_invalid_deploy.py +0 -24
  33. tests/examples/tests/test_llm_erc20.py +0 -60
  34. tests/examples/tests/test_llm_erc20_analyze.py +0 -54
  35. tests/examples/tests/test_log_indexer.py +0 -76
  36. tests/examples/tests/test_multi_file_contract.py +0 -15
  37. tests/examples/tests/test_multi_read_erc20.py +0 -103
  38. tests/examples/tests/test_multi_tenant_storage.py +0 -76
  39. tests/examples/tests/test_read_erc20.py +0 -38
  40. tests/examples/tests/test_simple_time_contract.py +0 -90
  41. tests/examples/tests/test_storage.py +0 -26
  42. tests/examples/tests/test_user_storage.py +0 -87
  43. tests/examples/tests/test_wizard_of_coin.py +0 -27
  44. tests/gltest/__init__.py +0 -0
  45. tests/gltest/artifact/__init__.py +0 -0
  46. tests/gltest/artifact/contracts/duplicate_ic_contract_1.py +0 -22
  47. tests/gltest/artifact/contracts/duplicate_ic_contract_2.py +0 -22
  48. tests/gltest/artifact/contracts/not_ic_contract.py +0 -22
  49. tests/gltest/artifact/test_contract_definition.py +0 -55
  50. tests/gltest/assertions/test_assertions.py +0 -344
  51. tests/gltest_cli/__init__.py +0 -0
  52. tests/gltest_cli/config/test_config_integration.py +0 -432
  53. tests/gltest_cli/config/test_general_config.py +0 -406
  54. tests/gltest_cli/config/test_plugin.py +0 -290
  55. tests/gltest_cli/config/test_user.py +0 -411
  56. {genlayer_test-0.7.0.dist-info → genlayer_test-0.9.0.dist-info}/WHEEL +0 -0
  57. {genlayer_test-0.7.0.dist-info → genlayer_test-0.9.0.dist-info}/entry_points.txt +0 -0
  58. {genlayer_test-0.7.0.dist-info → genlayer_test-0.9.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,370 +0,0 @@
1
- # v0.1.0
2
- # { "Depends": "py-genlayer:test" }
3
-
4
- import json
5
- from enum import Enum
6
- from datetime import datetime, timezone
7
- from urllib.parse import urlparse
8
- from genlayer import *
9
-
10
-
11
- class Status(Enum):
12
- ACTIVE = "Active"
13
- RESOLVED = "Resolved"
14
- ERROR = "Error"
15
-
16
-
17
- class IntelligentOracle(gl.Contract):
18
- # Declare persistent storage fields
19
- prediction_market_id: str
20
- title: str
21
- description: str
22
- potential_outcomes: DynArray[str]
23
- rules: DynArray[str]
24
- data_source_domains: DynArray[str]
25
- resolution_urls: DynArray[str]
26
- earliest_resolution_date: str # Store as ISO format string
27
- status: str # Store as string since Enum isn't supported
28
- analysis: str # Store analysis results
29
- outcome: str
30
-
31
- def __init__(
32
- self,
33
- prediction_market_id: str,
34
- title: str,
35
- description: str,
36
- potential_outcomes: list[str],
37
- rules: list[str],
38
- data_source_domains: list[str],
39
- resolution_urls: list[str],
40
- earliest_resolution_date: str,
41
- ):
42
- if (
43
- not prediction_market_id
44
- or not title
45
- or not description
46
- or not potential_outcomes
47
- or not rules
48
- or not earliest_resolution_date
49
- ):
50
- raise ValueError("Missing required fields.")
51
-
52
- if not resolution_urls and not data_source_domains:
53
- raise ValueError("Missing resolution URLs or data source domains.")
54
-
55
- if len(resolution_urls) > 0 and len(data_source_domains) > 0:
56
- raise ValueError(
57
- "Cannot provide both resolution URLs and data source domains."
58
- )
59
-
60
- if len(potential_outcomes) < 2:
61
- raise ValueError("At least two potential outcomes are required.")
62
-
63
- if len(potential_outcomes) != len(set(potential_outcomes)):
64
- raise ValueError("Potential outcomes must be unique.")
65
-
66
- self.prediction_market_id = prediction_market_id
67
- self.title = title
68
- self.description = description
69
-
70
- for outcome in potential_outcomes:
71
- self.potential_outcomes.append(outcome.strip())
72
-
73
- for rule in rules:
74
- self.rules.append(rule)
75
-
76
- for datasource in data_source_domains:
77
- self.data_source_domains.append(
78
- datasource.strip()
79
- .lower()
80
- .replace("http://", "")
81
- .replace("https://", "")
82
- .replace("www.", "")
83
- )
84
-
85
- for url in resolution_urls:
86
- self.resolution_urls.append(url.strip())
87
-
88
- self.earliest_resolution_date = earliest_resolution_date
89
- self.status = Status.ACTIVE.value
90
-
91
- self.outcome = ""
92
-
93
- @gl.public.view
94
- def _check_evidence_domain(self, evidence: str) -> bool:
95
- try:
96
- parsed_url = urlparse(evidence)
97
- evidence_domain = parsed_url.netloc.lower().replace("www.", "")
98
- return evidence_domain in self.data_source_domains
99
- except Exception:
100
- return False
101
-
102
- @gl.public.write
103
- def resolve(self, evidence_url: str = "") -> None:
104
- if self.status == Status.RESOLVED.value:
105
- raise ValueError("Cannot resolve an already resolved oracle.")
106
-
107
- current_time = datetime.now().astimezone().date()
108
- earliest_time = datetime.fromisoformat(self.earliest_resolution_date).date()
109
- if current_time < earliest_time:
110
- raise ValueError("Cannot resolve before the earliest resolution date.")
111
-
112
- if len(self.resolution_urls) > 0 and evidence_url:
113
- raise ValueError(
114
- "An evidence URL was provided but the oracle is configured to use resolution URLs already provided."
115
- )
116
-
117
- if len(self.resolution_urls) == 0 and not evidence_url:
118
- raise ValueError(
119
- "No evidence URL provided and the oracle is not configured to use resolution URLs."
120
- )
121
-
122
- if evidence_url:
123
- is_valid = self._check_evidence_domain(evidence_url)
124
- if not is_valid:
125
- raise ValueError(
126
- "The evidence URL does not match any of the data source domains."
127
- )
128
-
129
- analyzed_outputs = []
130
- resources_to_check = (
131
- self.resolution_urls if len(self.resolution_urls) > 0 else [evidence_url]
132
- )
133
-
134
- title = self.title
135
- description = self.description
136
- potential_outcomes = list(self.potential_outcomes)
137
- rules = list(self.rules)
138
- earliest_resolution_date = self.earliest_resolution_date
139
-
140
- for resource_url in resources_to_check:
141
-
142
- def evaluate_single_source() -> str:
143
- resource_web_data = gl.nondet.web.render(resource_url, mode="text")
144
- print(resource_web_data)
145
-
146
- task = f"""
147
- You are an AI Validator tasked with resolving a prediction market.
148
- Your goal is to determine the correct outcome based on the user-defined rules,
149
- the provided webpage HTML content, the resolution date, and the list of potential outcomes.
150
-
151
- ### Inputs
152
- <title>
153
- {title}
154
- </title>
155
-
156
- <description>
157
- {description}
158
- </description>
159
-
160
- <potential_outcomes>
161
- {potential_outcomes}
162
- </potential_outcomes>
163
-
164
- <rules>
165
- {rules}
166
- </rules>
167
-
168
- <source_url>
169
- {resource_url}
170
- </source_url>
171
-
172
- <webpage_content>
173
- {resource_web_data}
174
- </webpage_content>
175
-
176
- <current_date>
177
- {datetime.now().astimezone()}
178
- </current_date>
179
-
180
- <earliest_resolution_date>
181
- {earliest_resolution_date}
182
- </earliest_resolution_date>
183
-
184
-
185
-
186
-
187
- ### **Your Task:**
188
- 1. **Analyze the Inputs:**
189
- - Carefully read and interpret the user-defined rules.
190
- - Parse the HTML content to extract meaningful information relevant to the rules.
191
- - Determine if the source pertains to the event that is being predicted.
192
- - Determine if the event has occurred yet.
193
-
194
- 2. **Provide Reasoning:**
195
- - Write a clear, self-contained reasoning for the outcome.
196
- - Reference specific parts of the rules and the extracted data that support your decision.
197
- - Ensure that someone reading the reasoning can understand it without needing additional information.
198
-
199
- 3. **Determine The Outcome:**
200
- - Based on your analysis, decide which potential outcome is correct.
201
- - If an outcome can be determined, but the outcome is not in the list of potential outcomes, the outcome should be `ERROR`.
202
- - If the information is insufficient or inconclusive, or the event has not occurred yet, and you cannot confidently determine an outcome based on this source, the outcome should be `UNDETERMINED`.
203
-
204
-
205
-
206
-
207
- ### **Output Format:**
208
-
209
- Provide your response in **valid JSON** format with the following structure:
210
-
211
- ```json
212
- {{
213
- "valid_source": "true | false",
214
- "event_has_occurred": "true | false",
215
- "reasoning": "Your detailed reasoning here",
216
- "outcome": "Chosen outcome from the potential outcomes list, `UNDETERMINED` if no outcome can be determined based on this source, `ERROR` if the outcome is not in the potential outcomes list"
217
- }}
218
- ```
219
-
220
- ### **Constraints and Considerations:**
221
-
222
- - **Accuracy:** Base your decision strictly on the provided inputs.
223
- - **Objectivity:** Remain neutral and unbiased.
224
- - **Clarity:** Make sure your reasoning is easy to understand.
225
- - **Validity:** Ensure the JSON output is properly formatted and free of errors. Do not include trailing commas.
226
- """
227
- result = gl.nondet.exec_prompt(task)
228
- print(result)
229
- return result
230
-
231
- result = gl.eq_principle.prompt_comparative(
232
- evaluate_single_source,
233
- principle="`outcome` field must be exactly the same. All other fields must be similar",
234
- )
235
-
236
- result_dict = _parse_json_dict(result)
237
- analyzed_outputs.append((resource_url, result_dict))
238
-
239
- def evaluate_all_sources() -> str:
240
- task = f"""
241
- You are an AI Validator tasked with resolving a prediction market Oracle. Your goal is to determine
242
- the correct outcome based on processed data from all of the individial data sources. Here are your inputs
243
-
244
- ### Inputs
245
- <title>
246
- {title}
247
- </title>
248
-
249
- <description>
250
- {description}
251
- </description>
252
-
253
- <potential_outcomes>
254
- {potential_outcomes}
255
- </potential_outcomes>
256
-
257
- <rules>
258
- {rules}
259
- </rules>
260
-
261
- <processed_data>
262
- {analyzed_outputs}
263
- </processed_data>
264
-
265
- <current_date>
266
- {datetime.now().astimezone()}
267
- </current_date>
268
-
269
- <earliest_resolution_date>
270
- {earliest_resolution_date}
271
- </earliest_resolution_date>
272
-
273
- ### **Your Task:**
274
- 1. **Analyze the Inputs:**
275
- - Carefully read and interpret the user-defined rules.
276
- - Take into account all the processed data form the sources.
277
- - Consider the resolution date in your analysis to ensure timeliness of the data.
278
-
279
- 2. **Determine The Outcome:**
280
- - The output should be determined from the processed data form the resolution sources.
281
- - Based on your analysis, decide which potential outcome is correct.
282
- - If an outcome can be determined, but the outcome is not in the list of potential outcomes, the outcome should be `ERROR`.
283
- - If the information is insufficient or inconclusive, and you cannot confidently determine an outcome, the outcome should be `UNDETERMINED`.
284
- - Your response should reflect a coherent summary outcome from the previous analysis.
285
- - If multiple sources contradict each other, refer to the rules to determine how to resolve the contradiction.
286
- - If the rules do not provide a clear resolution, the outcome should be `ERROR`.
287
-
288
- ### **Output Format:**
289
-
290
- Provide your response in **valid JSON** format with the following structure:
291
-
292
- ```json
293
- {{
294
- "relevant_sources": "List of URLs that are relevant to the outcome",
295
- "reasoning": "Your detailed reasoning here",
296
- "outcome": "Chosen outcome from the potential outcomes list, `UNDETERMINED` if undetermined, `ERROR` if the outcome is not in the potential outcomes list"
297
- }}
298
- ```
299
-
300
- ### **Constraints and Considerations:**
301
-
302
- - **Accuracy:** Base your decision strictly on the provided inputs.
303
- - **Objectivity:** Remain neutral and unbiased.
304
- - **Clarity:** Make sure your reason is easy to understand.
305
- - **Validity:** Ensure the JSON output is properly formatted and free of errors. Do not include trailing commas.
306
-
307
- """
308
-
309
- result = gl.nondet.exec_prompt(task)
310
- print(result)
311
- return result
312
-
313
- result = gl.eq_principle.prompt_comparative(
314
- evaluate_all_sources,
315
- principle="`outcome` field must be exactly the same. All other fields must be similar",
316
- )
317
-
318
- result_dict = _parse_json_dict(result)
319
- self.analysis = json.dumps(result_dict)
320
-
321
- if result_dict["outcome"] == "UNDETERMINED":
322
- return
323
-
324
- if (
325
- result_dict["outcome"] == "ERROR"
326
- or result_dict["outcome"] not in self.potential_outcomes
327
- ):
328
- self.status = Status.ERROR.value
329
- return
330
-
331
- self.outcome = result_dict["outcome"]
332
- self.status = Status.RESOLVED.value
333
-
334
- @gl.public.view
335
- def get_dict(self) -> dict[str, str | list[str]]:
336
- return {
337
- "title": self.title,
338
- "description": self.description,
339
- "potential_outcomes": list(self.potential_outcomes),
340
- "rules": list(self.rules),
341
- "data_source_domains": list(self.data_source_domains),
342
- "resolution_urls": list(self.resolution_urls),
343
- "status": self.status,
344
- "earliest_resolution_date": self.earliest_resolution_date,
345
- "analysis": self.analysis,
346
- "outcome": self.outcome,
347
- "prediction_market_id": self.prediction_market_id,
348
- }
349
-
350
- @gl.public.view
351
- def get_status(self) -> str:
352
- return self.status
353
-
354
-
355
- def _parse_json_dict(json_str: str) -> dict:
356
- """
357
- Used to sanitize the JSON output from the LLM.
358
- Remove everything before the first '{' and after the last '}', and remove trailing commas before closing braces/brackets
359
- """
360
- first_brace = json_str.find("{")
361
- last_brace = json_str.rfind("}")
362
- json_str = json_str[first_brace : last_brace + 1]
363
-
364
- # Remove trailing commas before closing braces/brackets
365
- import re
366
-
367
- json_str = re.sub(r",(?!\s*?[\{\[\"\'\w])", "", json_str)
368
- print(json_str)
369
-
370
- return json.loads(json_str)
@@ -1,49 +0,0 @@
1
- # v0.1.0
2
- # { "Depends": "py-genlayer:test" }
3
-
4
- from genlayer import *
5
-
6
-
7
- class Registry(gl.Contract):
8
- # Declare persistent storage fields
9
- contract_addresses: DynArray[str]
10
- intelligent_oracle_code: str
11
-
12
- def __init__(self, intelligent_oracle_code: str):
13
- self.intelligent_oracle_code = intelligent_oracle_code
14
-
15
- @gl.public.write
16
- def create_new_prediction_market(
17
- self,
18
- prediction_market_id: str,
19
- title: str,
20
- description: str,
21
- potential_outcomes: list[str],
22
- rules: list[str],
23
- data_source_domains: list[str],
24
- resolution_urls: list[str],
25
- earliest_resolution_date: str,
26
- ) -> None:
27
- registered_contracts = len(self.contract_addresses)
28
- contract_address = gl.deploy_contract(
29
- code=self.intelligent_oracle_code.encode("utf-8"),
30
- args=[
31
- prediction_market_id,
32
- title,
33
- description,
34
- potential_outcomes,
35
- rules,
36
- data_source_domains,
37
- resolution_urls,
38
- earliest_resolution_date,
39
- ],
40
- salt_nonce=registered_contracts + 1,
41
- on="accepted",
42
- )
43
- print("contract_address", contract_address)
44
- print("contract_address type", type(contract_address))
45
- self.contract_addresses.append(contract_address.as_hex)
46
-
47
- @gl.public.view
48
- def get_contract_addresses(self) -> list[str]:
49
- return list(self.contract_addresses)
@@ -1,10 +0,0 @@
1
- # { "Depends": "py-genlayer:test" }
2
-
3
- import genlayer as gl
4
-
5
-
6
- class InvalidDeploy(gl.Contract):
7
- """Contract that always fails during deployment"""
8
-
9
- def __init__(self):
10
- raise Exception("This is an invalid deploy")
@@ -1,70 +0,0 @@
1
- # v0.1.0
2
- # { "Depends": "py-genlayer:latest" }
3
-
4
- import json
5
-
6
- from genlayer import *
7
-
8
-
9
- class LlmErc20(gl.Contract):
10
- balances: TreeMap[Address, u256]
11
-
12
- def __init__(self, total_supply: int) -> None:
13
- self.balances[gl.message.sender_address] = u256(total_supply)
14
-
15
- @gl.public.write
16
- def transfer(self, amount: int, to_address: str) -> None:
17
- input = f"""
18
- You keep track of transactions between users and their balance in coins.
19
- The current balance for all users in JSON format is:
20
- {json.dumps(self.get_balances())}
21
- The transaction to compute is: {{
22
- sender: "{gl.message.sender_address.as_hex}",
23
- recipient: "{Address(to_address).as_hex}",
24
- amount: {amount},
25
- }}
26
-
27
- """
28
- task = """For every transaction, validate that the user sending the Coins has
29
- enough balance. If any transaction is invalid, it shouldn't be processed.
30
- Update the balances based on the valid transactions only.
31
- Given the current balance in JSON format and the transaction provided,
32
- please provide the result of your calculation with the following format:
33
- {{
34
- "transaction_success": bool, // Whether the transaction was successful
35
- "transaction_error": str, // Empty if transaction is successful
36
- "updated_balances": object<str, int> // Updated balances after the transaction
37
- }}
38
-
39
- It is mandatory that you respond only using the JSON format above,
40
- nothing else. Don't include any other words or characters,
41
- your output must be only JSON without any formatting prefix or suffix.
42
- This result should be perfectly parsable by a JSON parser without errors.
43
- """
44
-
45
- criteria = """
46
- The balance of the sender should have decreased by the amount sent.
47
- The balance of the receiver should have increased by the amount sent.
48
- The total sum of all balances should remain the same before and after the transaction"""
49
-
50
- final_result = (
51
- gl.eq_principle.prompt_non_comparative(
52
- lambda: input,
53
- task=task,
54
- criteria=criteria,
55
- )
56
- .replace("```json", "")
57
- .replace("```", "")
58
- )
59
- print("final_result: ", final_result)
60
- result_json = json.loads(final_result)
61
- for k, v in result_json["updated_balances"].items():
62
- self.balances[Address(k)] = v
63
-
64
- @gl.public.view
65
- def get_balances(self) -> dict[str, int]:
66
- return {k.as_hex: v for k, v in self.balances.items()}
67
-
68
- @gl.public.view
69
- def get_balance_of(self, address: str) -> int:
70
- return self.balances.get(Address(address), 0)
@@ -1,69 +0,0 @@
1
- # v0.1.0
2
- # {
3
- # "Seq": [
4
- # { "Depends": "py-lib-genlayer-embeddings:09h0i209wrzh4xzq86f79c60x0ifs7xcjwl53ysrnw06i54ddxyi" },
5
- # { "Depends": "py-genlayer:latest" }
6
- # ]
7
- # }
8
-
9
- import numpy as np
10
- from genlayer import *
11
- import genlayer_embeddings as gle
12
-
13
- from dataclasses import dataclass
14
- import typing
15
-
16
-
17
- @allow_storage
18
- @dataclass
19
- class StoreValue:
20
- log_id: u256
21
- text: str
22
-
23
-
24
- # contract class
25
- class LogIndexer(gl.Contract):
26
- vector_store: gle.VecDB[np.float32, typing.Literal[384], StoreValue]
27
-
28
- def __init__(self):
29
- pass
30
-
31
- def get_embedding_generator(self):
32
- return gle.SentenceTransformer("all-MiniLM-L6-v2")
33
-
34
- def get_embedding(
35
- self, txt: str
36
- ) -> np.ndarray[tuple[typing.Literal[384]], np.dtypes.Float32DType]:
37
- return self.get_embedding_generator()(txt)
38
-
39
- @gl.public.view
40
- def get_closest_vector(self, text: str) -> dict | None:
41
- emb = self.get_embedding(text)
42
- result = list(self.vector_store.knn(emb, 1))
43
- if len(result) == 0:
44
- return None
45
- result = result[0]
46
- return {
47
- "vector": list(str(x) for x in result.key),
48
- "similarity": str(1 - result.distance),
49
- "id": result.value.log_id,
50
- "text": result.value.text,
51
- }
52
-
53
- @gl.public.write
54
- def add_log(self, log: str, log_id: int) -> None:
55
- emb = self.get_embedding(log)
56
- self.vector_store.insert(emb, StoreValue(text=log, log_id=u256(log_id)))
57
-
58
- @gl.public.write
59
- def update_log(self, log_id: int, log: str) -> None:
60
- emb = self.get_embedding(log)
61
- for elem in self.vector_store.knn(emb, 2):
62
- if elem.value.text == log:
63
- elem.value.log_id = u256(log_id)
64
-
65
- @gl.public.write
66
- def remove_log(self, id: int) -> None:
67
- for el in self.vector_store:
68
- if el.value.log_id == id:
69
- el.remove()
@@ -1,24 +0,0 @@
1
- from genlayer import *
2
-
3
-
4
- class MultiFileContract(gl.Contract):
5
- other_addr: Address
6
-
7
- def __init__(self):
8
- with open("/contract/other.py", "rt") as f:
9
- text = f.read()
10
- self.other_addr = gl.deploy_contract(
11
- code=text.encode("utf-8"),
12
- args=["123"],
13
- salt_nonce=u256(1),
14
- value=u256(0),
15
- on="accepted",
16
- )
17
-
18
- @gl.public.write
19
- def wait(self) -> None:
20
- pass
21
-
22
- @gl.public.view
23
- def test(self) -> str:
24
- return gl.get_contract_at(self.other_addr).view().test()
@@ -1,14 +0,0 @@
1
- # { "Depends": "py-genlayer:test" }
2
-
3
- from genlayer import *
4
-
5
-
6
- class Other(gl.Contract):
7
- data: str
8
-
9
- def __init__(self, data: str):
10
- self.data = data
11
-
12
- @gl.public.view
13
- def test(self) -> str:
14
- return self.data
@@ -1,29 +0,0 @@
1
- # v0.1.0
2
- # { "Depends": "py-genlayer:test" }
3
-
4
- from genlayer import *
5
-
6
-
7
- class multi_read_erc20(gl.Contract):
8
- balances: TreeMap[Address, TreeMap[Address, u256]]
9
-
10
- def __init__(self):
11
- pass
12
-
13
- @gl.public.write
14
- def update_token_balances(
15
- self, account_address: str, token_contracts: list[str]
16
- ) -> None:
17
- for token_contract in token_contracts:
18
- contract = gl.get_contract_at(Address(token_contract))
19
- balance = contract.view().get_balance_of(account_address)
20
- self.balances.get_or_insert_default(Address(account_address))[
21
- Address(token_contract)
22
- ] = balance
23
-
24
- @gl.public.view
25
- def get_balances(self) -> dict[str, dict[str, int]]:
26
- return {
27
- k.as_hex: {k.as_hex: v for k, v in v.items()}
28
- for k, v in self.balances.items()
29
- }
@@ -1,51 +0,0 @@
1
- # v0.1.0
2
- # { "Depends": "py-genlayer:test" }
3
-
4
- from genlayer import *
5
-
6
-
7
- class MultiTentantStorage(gl.Contract):
8
- """
9
- Same functionality as UserStorage, but implemented with multiple storage contracts.
10
- Each user is assigned to a storage contract, and all storage contracts are managed by this same contract.
11
- This contract does not prevent users from directly interacting with the storage contracts, but it doesn't bother us for testing purposes.
12
- This is done to test contract calls between different contracts.
13
- """
14
-
15
- all_storage_contracts: DynArray[Address]
16
- available_storage_contracts: DynArray[Address]
17
- mappings: TreeMap[
18
- Address, Address
19
- ] # mapping of user address to storage contract address
20
-
21
- def __init__(self, storage_contracts: list[str]):
22
- for el in storage_contracts:
23
- self.all_storage_contracts.append(Address(el))
24
- self.available_storage_contracts.append(Address(el))
25
-
26
- @gl.public.view
27
- def get_available_contracts(self) -> list[str]:
28
- return [x.as_hex for x in self.available_storage_contracts]
29
-
30
- @gl.public.view
31
- def get_all_storages(self) -> dict[str, str]:
32
- return {
33
- storage_contract.as_hex: gl.get_contract_at(storage_contract)
34
- .view()
35
- .get_storage()
36
- for storage_contract in self.all_storage_contracts
37
- }
38
-
39
- @gl.public.write
40
- def update_storage(self, new_storage: str) -> None:
41
- # Assign user to a storage contract if not already assigned
42
- if gl.message.sender_address not in self.mappings:
43
- self.mappings[gl.message.sender_address] = self.available_storage_contracts[
44
- -1
45
- ]
46
- self.available_storage_contracts.pop()
47
-
48
- contract_to_use = self.mappings[gl.message.sender_address]
49
- gl.get_contract_at(contract_to_use).emit(on="accepted").update_storage(
50
- new_storage
51
- )