diff --git a/pages/api-references/genlayer-py.mdx b/pages/api-references/genlayer-py.mdx index e1e949219..ca17857ed 100644 --- a/pages/api-references/genlayer-py.mdx +++ b/pages/api-references/genlayer-py.mdx @@ -48,12 +48,14 @@ Waits for a transaction receipt. receipt = client.wait_for_transaction_receipt( transaction_hash=transaction_hash, status='FINALIZED', # or 'ACCEPTED' + full_transaction=False, # Optional: False for simplified receipt, True for complete ) ``` **Parameters:** - `transaction_hash`: The transaction hash - `status`: The desired transaction status ('FINALIZED' or 'ACCEPTED') +- `full_transaction`: (Optional) `False` (default) returns a simplified receipt with binary data removed; `True` returns the complete receipt with all fields **Returns:** Transaction receipt object @@ -65,8 +67,9 @@ Reads data from a deployed contract. ```python result = client.read_contract( address=contract_address, - function_name: 'get_complete_storage', - args: [], + function_name='get_complete_storage', + args=[], + state_status='accepted', # Optional: 'accepted' or 'finalized' ) ``` @@ -75,6 +78,7 @@ result = client.read_contract( - `address`: The contract address - `function_name`: The name of the function to call - `args`: An array of arguments for the function call +- `state_status`: (Optional) The state to query against (`'accepted'` or `'finalized'`) **Returns:** The result of the contract function call
@@ -132,11 +136,15 @@ account_with_key = create_account('0x1234...') # Replace with actual private key ## Chain Information -### localnet +### Available Chains -Provides configuration for the local GenLayer Studio chain. ```python -from genlayer_py.chains import localnet +from genlayer_py.chains import localnet, studionet, testnet_asimov ``` + +- **localnet**: Local development network (GenLayer Studio) +- **studionet**: Hosted development environment +- **testnet_asimov**: Public test network + **Usage:** Used when creating a client to specify the chain diff --git a/pages/api-references/genlayer-test.mdx b/pages/api-references/genlayer-test.mdx index e4fad593d..6aa52bd6b 100644 --- a/pages/api-references/genlayer-test.mdx +++ b/pages/api-references/genlayer-test.mdx @@ -10,6 +10,88 @@ For comprehensive test examples and implementation patterns, see our [Test Suite pip install genlayer-test ``` +## Two Testing Modes + +The testing suite provides two execution modes: + +| | Direct Mode | Studio Mode | +|---|---|---| +| **How it works** | Runs contract Python code directly in-memory | Deploys to GenLayer Studio, interacts via RPC | +| **Speed** | ~milliseconds per test | ~minutes per test | +| **Prerequisites** | Python >= 3.12 | Python >= 3.12 + GenLayer Studio (Docker) | +| **Best for** | Unit tests, rapid development, CI/CD | Integration tests, consensus validation, testnet | + +**Start with Direct Mode** — it's faster, simpler, and doesn't require Docker. Use Studio Mode when you need full network behavior or multi-validator consensus. + +## Direct Mode + +Run contracts directly in Python — no simulator, no Docker, no network. Tests execute in milliseconds. + +### Quick Start + +```python +def test_storage(direct_vm, direct_deploy): + # Deploy contract in-memory + storage = direct_deploy("contracts/Storage.py", "initial") + + # Read state directly + assert storage.get_storage() == "initial" + + # Write state directly + storage.update_storage("updated") + assert storage.get_storage() == "updated" +``` + +Run with pytest: + +```bash +pytest tests/ -v +``` + +### Direct Mode Fixtures + +| Fixture | Description | +|---------|-------------| +| `direct_vm` | VM context with cheatcodes | +| `direct_deploy` | Deploy contracts directly | +| `direct_alice`, `direct_bob`, `direct_charlie` | Test addresses | +| `direct_owner` | Default sender address | +| `direct_accounts` | List of 10 test addresses | + +### Cheatcodes + +```python +# Change sender +direct_vm.sender = alice + +# Prank (temporary sender change) +with direct_vm.prank(bob): + contract.method() # Called as bob + +# Snapshots (captures full state: storage, mocks, sender, validators) +snap_id = direct_vm.snapshot() +contract.modify_state() +direct_vm.revert(snap_id) # Full state restored + +# Expect revert +with direct_vm.expect_revert("Insufficient balance"): + contract.transfer(bob, 1000000) + +# Mock web/LLM (regex pattern matching) +direct_vm.mock_web(r"api\.example\.com", {"status": 200, "body": "{}"}) +direct_vm.mock_llm(r"analyze.*", "positive sentiment") + +# Test validator consensus logic +contract.update_price() # Runs leader_fn, captures validator +direct_vm.clear_mocks() # Swap mocks for validator +direct_vm.mock_llm(r".*", "different result") +assert direct_vm.run_validator() is False # Validator disagrees +``` + +## Studio Mode + +The rest of this document covers Studio Mode — deploying contracts to a running GenLayer Studio instance and interacting via RPC. + ## Configuration The GenLayer Testing Suite can be configured using an optional `gltest.config.yaml` file in your project root. While not required, this file helps manage network configurations, contract paths, and environment settings. @@ -493,7 +575,7 @@ The Mock LLM system allows you to simulate Large Language Model responses in Gen ```python mock_response = { - "response": {}, # Optional: mocks gl.nondet.exec_prompt + "nondet_exec_prompt": {}, # Optional: mocks gl.nondet.exec_prompt "eq_principle_prompt_comparative": {}, # Optional: mocks gl.eq_principle.prompt_comparative "eq_principle_prompt_non_comparative": {} # Optional: mocks gl.eq_principle.prompt_non_comparative } @@ -503,9 +585,11 @@ setup_validators(mock_response) ### Method Mappings -- "response" -> gl.nondet.exec_prompt -- "eq_principle_prompt_comparative" -> gl.eq_principle.prompt_comparative -- "eq_principle_prompt_non_comparative" -> gl.eq_principle.prompt_non_comparative +| Mock Key | GenLayer Method | +|----------|----------------| +| `"nondet_exec_prompt"` | `gl.nondet.exec_prompt` | +| `"eq_principle_prompt_comparative"` | `gl.eq_principle.prompt_comparative` | +| `"eq_principle_prompt_non_comparative"` | `gl.eq_principle.prompt_non_comparative` | ### How It Works @@ -534,7 +618,7 @@ from gltest import get_contract_factory def test_with_mocked_llm(setup_validators): mock_response = { - "response": { + "nondet_exec_prompt": { "What is the weather?": "It's sunny today", "Calculate 2+2": "4" }, diff --git a/pages/developers/decentralized-applications/dapp-development-workflow.mdx b/pages/developers/decentralized-applications/dapp-development-workflow.mdx index ce4ecf978..69b870921 100644 --- a/pages/developers/decentralized-applications/dapp-development-workflow.mdx +++ b/pages/developers/decentralized-applications/dapp-development-workflow.mdx @@ -13,8 +13,8 @@ It provides an interactive environment that serves as a comprehensive sandbox fo The platform runs a simulated network with customizable validators that accurately mirror the GenLayer consensus mechanism. This feature allows developers to test their contracts under conditions that closely resemble the actual blockchain environment, ensuring reliable deployment outcomes. ### Getting Started: -1. **Set Up the Studio**: Developers initialize the Studio using `genlayer cli` command `genlayer init` which configures the environment and spawns a local validator network. GenLayer Studio is also available as a hosted instace at [studio.genlayer.com](https://studio.genlayer.com/). -2. **Write Your First Contract**: Intelligent Contracts in GenLayer are written in Python, utilizing its extensive libraries and GenVM capabilities like LLM calls and web integration. Refer to [Your First Contract](/developers/intelligent-contracts/your-first-contract) guide for more information. +1. **Set Up the Studio**: Developers initialize the Studio using `genlayer cli` command `genlayer init` which configures the environment and spawns a local validator network. GenLayer Studio is also available as a hosted instance at [studio.genlayer.com](https://studio.genlayer.com/). +2. **Write Your First Contract**: Intelligent Contracts in GenLayer are written in Python, utilizing its extensive libraries and GenVM capabilities like LLM calls and web integration. Refer to [Your First Contract](/developers/intelligent-contracts/first-contract) guide for more information. 3. **Deploy and Test**: Deploy your Intelligent Contracts through the Studio interface and test them in the simulated network. --- diff --git a/pages/developers/decentralized-applications/genlayer-js.mdx b/pages/developers/decentralized-applications/genlayer-js.mdx index ec480ecda..226dca20f 100644 --- a/pages/developers/decentralized-applications/genlayer-js.mdx +++ b/pages/developers/decentralized-applications/genlayer-js.mdx @@ -78,4 +78,4 @@ You can find the GenLayerJS SDK repository on GitHub: ## Full Reference -The full reference for the GenLayerJS SDK is available in the [GenLayerJS SDK Reference](/references/genlayer-js). \ No newline at end of file +The full reference for the GenLayerJS SDK is available in the [GenLayerJS SDK Reference](/api-references/genlayer-js). \ No newline at end of file diff --git a/pages/developers/intelligent-contracts/examples/fetch-github-profile.mdx b/pages/developers/intelligent-contracts/examples/fetch-github-profile.mdx index 126cc8a14..26382e2eb 100644 --- a/pages/developers/intelligent-contracts/examples/fetch-github-profile.mdx +++ b/pages/developers/intelligent-contracts/examples/fetch-github-profile.mdx @@ -20,9 +20,9 @@ class FetchGitHubProfile(gl.Contract): github_profile_url = "https://github.com/"+github_handle def fetch_github_profile_page_content() -> str: - return gl.get_webpage(github_profile_url, mode="text") + return gl.nondet.web.render(github_profile_url, mode="text") - self.github_profile = gl.eq_principle_strict_eq(fetch_github_profile_page_content) + self.github_profile = gl.eq_principle.strict_eq(fetch_github_profile_page_content) @gl.public.view def show_github_profile(self) -> str: @@ -35,14 +35,14 @@ class FetchGitHubProfile(gl.Contract): - **Write Method**: - `fetch_github_profile(github_handle)` takes a GitHub username and retrieves their profile content. - Constructs the profile URL using the provided handle. - - Uses `gl.eq_principle_strict_eq()` to ensure all nodes agree on the same profile content. + - Uses `gl.eq_principle.strict_eq()` to ensure all nodes agree on the same profile content. - **Read Method**: - `show_github_profile()` returns the stored profile content. ## Key Components -1. **GitHub Integration**: The contract uses `gl.get_webpage()` to fetch content from GitHub profiles. -2. **Deterministic Execution**: `gl.eq_principle_strict_eq()` ensures that all nodes in the network arrive at the same exact content. +1. **GitHub Integration**: The contract uses `gl.nondet.web.render()` to fetch content from GitHub profiles. +2. **Deterministic Execution**: `gl.eq_principle.strict_eq()` ensures that all nodes in the network arrive at the same exact content. 3. **State Management**: The contract maintains a single string state variable that stores the profile content. ## Deploying the Contract diff --git a/pages/developers/intelligent-contracts/examples/fetch-web-content.mdx b/pages/developers/intelligent-contracts/examples/fetch-web-content.mdx index 9f28cd50e..2d90bb3c0 100644 --- a/pages/developers/intelligent-contracts/examples/fetch-web-content.mdx +++ b/pages/developers/intelligent-contracts/examples/fetch-web-content.mdx @@ -19,9 +19,9 @@ class FetchWebContent(gl.Contract): def fetch_web_content(self) -> typing.Any: def fetch_web_url_content() -> str: - return gl.get_webpage("https://example.com/", mode="text") + return gl.nondet.web.render("https://example.com/", mode="text") - self.content = gl.eq_principle_strict_eq(fetch_web_url_content) + self.content = gl.eq_principle.strict_eq(fetch_web_url_content) @gl.public.view def show_content(self) -> str: @@ -33,15 +33,15 @@ class FetchWebContent(gl.Contract): - **Initialization**: The `FetchWebContent` class initializes with an empty string in the `content` variable. - **Write Method**: - `fetch_web_content()` retrieves content from a web page and stores it. - - It contains an inner function `fetch_web_url_content()` that uses `gl.get_webpage()` to fetch content. - - Uses `gl.eq_principle_strict_eq()` to ensure all nodes agree on the same content. + - It contains an inner function `fetch_web_url_content()` that uses `gl.nondet.web.render()` to fetch content. + - Uses `gl.eq_principle.strict_eq()` to ensure all nodes agree on the same content. - **Read Method**: - `show_content()` returns the stored web content. ## Key Components -1. **Web Integration**: The contract uses `gl.get_webpage()` to fetch content from web URLs. -2. **Deterministic Execution**: `gl.eq_principle_strict_eq()` ensures that all nodes in the network arrive at the same exact content. +1. **Web Integration**: The contract uses `gl.nondet.web.render()` to fetch content from web URLs. +2. **Deterministic Execution**: `gl.eq_principle.strict_eq()` ensures that all nodes in the network arrive at the same exact content. 3. **State Management**: The contract maintains a single string state variable that stores the web content. ## Deploying the Contract @@ -101,7 +101,7 @@ You can monitor the contract's behavior through transaction logs, which will sho ## HTML Mode for Web Content -The `gl.get_webpage()` function supports different modes for retrieving web content. While `mode="text"` returns the plain text content, `mode="html"` allows you to retrieve the complete HTML `` of the webpage. +The `gl.nondet.web.render()` function supports different modes for retrieving web content. While `mode="text"` returns the plain text content, `mode="html"` allows you to retrieve the complete HTML `` of the webpage. Here's an example of using HTML mode: @@ -115,9 +115,9 @@ class FetchHTMLContent(gl.Contract): @gl.public.write def fetch_html_content(self) -> typing.Any: def fetch_web_url_html() -> str: - return gl.get_webpage("https://example.com/", mode="html") + return gl.nondet.web.render("https://example.com/", mode="html") - self.html_content = gl.eq_principle_strict_eq(fetch_web_url_html) + self.html_content = gl.eq_principle.strict_eq(fetch_web_url_html) @gl.public.view def show_html_content(self) -> str: diff --git a/pages/developers/intelligent-contracts/examples/github-profile-projects.mdx b/pages/developers/intelligent-contracts/examples/github-profile-projects.mdx index 00fc79ca2..156986b6f 100644 --- a/pages/developers/intelligent-contracts/examples/github-profile-projects.mdx +++ b/pages/developers/intelligent-contracts/examples/github-profile-projects.mdx @@ -20,7 +20,7 @@ class GitHubProfilesRepositories(gl.Contract): github_profile_url = "https://github.com/"+github_handle def fetch_github_profile_repositories() -> int: - profile_web_page = gl.get_webpage(github_profile_url, mode="text") + profile_web_page = gl.nondet.web.render(github_profile_url, mode="text") # Regular expression to find the number between "Repositories" and "Projects" pattern = r"Repositories\s+(\d+)\s+Projects" @@ -33,7 +33,7 @@ class GitHubProfilesRepositories(gl.Contract): else: return 0 - repositories = gl.eq_principle_strict_eq(fetch_github_profile_repositories) + repositories = gl.eq_principle.strict_eq(fetch_github_profile_repositories) if repositories > 25: self.github_profiles.append(github_handle) @@ -55,9 +55,9 @@ class GitHubProfilesRepositories(gl.Contract): ## Key Components -1. **GitHub Integration**: Uses `gl.get_webpage()` to fetch profile content. +1. **GitHub Integration**: Uses `gl.nondet.web.render()` to fetch profile content. 2. **Pattern Matching**: Employs regular expressions to extract repository counts. -3. **Deterministic Execution**: Uses `gl.eq_principle_strict_eq()` to ensure network consensus. +3. **Deterministic Execution**: Uses `gl.eq_principle.strict_eq()` to ensure network consensus. 4. **Conditional Storage**: Only stores profiles meeting specific criteria. ## Deploying the Contract diff --git a/pages/developers/intelligent-contracts/examples/github-profile-summary.mdx b/pages/developers/intelligent-contracts/examples/github-profile-summary.mdx index de0606b46..bf4aca09c 100644 --- a/pages/developers/intelligent-contracts/examples/github-profile-summary.mdx +++ b/pages/developers/intelligent-contracts/examples/github-profile-summary.mdx @@ -25,9 +25,9 @@ class GitHubProfilesSummaries(gl.Contract): github_profile_url = "https://github.com/"+github_handle def fetch_github_profile_summaries() -> str: - return gl.get_webpage(github_profile_url, mode="text") + return gl.nondet.web.render(github_profile_url, mode="text") - profile_content = gl.eq_principle_strict_eq(fetch_github_profile_summaries) + profile_content = gl.eq_principle.strict_eq(fetch_github_profile_summaries) task = """Given the web page content of a github profile in HTML format, generate a comprehensive summary of the profile mentioning the key meta attributes and the GitHub contribution most important metrics""" @@ -35,7 +35,7 @@ summary of the profile mentioning the key meta attributes and the GitHub contrib criteria = """The summary provided should include different metrics and a summary of a GitHub profile""" profile_summary = ( - gl.eq_principle_prompt_non_comparative( + gl.eq_principle.prompt_non_comparative( lambda: profile_content, task=task, criteria=criteria, @@ -61,7 +61,7 @@ summary of the profile mentioning the key meta attributes and the GitHub contrib ## Key Components 1. **Data Storage**: Uses `TreeMap` for efficient key-value storage of profile summaries. -2. **Web Fetching**: Uses `gl.get_webpage()` with strict equivalence for deterministic content retrieval. +2. **Web Fetching**: Uses `gl.nondet.web.render()` with strict equivalence for deterministic content retrieval. 3. **AI Analysis**: Uses non-comparative equivalence for generating profile summaries. 4. **Duplicate Prevention**: Includes checks to prevent regenerating existing summaries. diff --git a/pages/developers/intelligent-contracts/examples/llm-hello-world-non-comparative.mdx b/pages/developers/intelligent-contracts/examples/llm-hello-world-non-comparative.mdx index e33f56587..0335bb1af 100644 --- a/pages/developers/intelligent-contracts/examples/llm-hello-world-non-comparative.mdx +++ b/pages/developers/intelligent-contracts/examples/llm-hello-world-non-comparative.mdx @@ -17,7 +17,7 @@ class LlmHelloWorldNonComparative(gl.Contract): @gl.public.write def set_message(self) -> typing.Any: - self.message = gl.eq_principle_prompt_non_comparative( + self.message = gl.eq_principle.prompt_non_comparative( lambda: "There is no context, I just want you to answer with truthy value in python (for example: 'yes', 'True', 1)", task="Answer with truthy value in python (for example: 'yes', 'True', 1)", criteria="Answer should be a truthy value in python" @@ -33,7 +33,7 @@ class LlmHelloWorldNonComparative(gl.Contract): - **Initialization**: The `LlmHelloWorldNonComparative` class initializes with an empty string in the `message` variable. - **Write Method**: - `set_message()` uses AI functionality to generate and store a message. - - Uses `gl.eq_principle_prompt_non_comparative()` with three parameters: + - Uses `gl.eq_principle.prompt_non_comparative()` with three parameters: - A lambda function providing the prompt - A task description - Validation criteria for the response @@ -43,7 +43,7 @@ class LlmHelloWorldNonComparative(gl.Contract): ## Key Components 1. **AI Integration**: The contract uses non-comparative equivalence principle to interact with an AI model. -2. **Deterministic Execution**: `gl.eq_principle_prompt_non_comparative()` ensures that all nodes in the network accept responses that meet the specified criteria. +2. **Deterministic Execution**: `gl.eq_principle.prompt_non_comparative()` ensures that all nodes in the network accept responses that meet the specified criteria. 3. **State Management**: The contract maintains a single string state variable that stores the AI response. ## Deploying the Contract diff --git a/pages/developers/intelligent-contracts/examples/llm-hello-world.mdx b/pages/developers/intelligent-contracts/examples/llm-hello-world.mdx index d79a29953..e5bc60ee9 100644 --- a/pages/developers/intelligent-contracts/examples/llm-hello-world.mdx +++ b/pages/developers/intelligent-contracts/examples/llm-hello-world.mdx @@ -20,11 +20,11 @@ class LlmHelloWorld(gl.Contract): def get_message() -> str: task = "There is no context, I just want you to answer with a string equal to 'yes'" - result = gl.exec_prompt(task) + result = gl.nondet.exec_prompt(task) print(result) return result - self.message = gl.eq_principle_strict_eq(get_message) + self.message = gl.eq_principle.strict_eq(get_message) @gl.public.view def get_message(self) -> str: @@ -37,14 +37,14 @@ class LlmHelloWorld(gl.Contract): - **Write Method**: - `set_message()` uses AI functionality to generate and store a message. - It contains an inner function `get_message()` that prompts an AI model with a simple task. - - Uses `gl.eq_principle_strict_eq()` to ensure deterministic AI responses across the network. + - Uses `gl.eq_principle.strict_eq()` to ensure deterministic AI responses across the network. - **Read Method**: - `get_message()` returns the stored message. ## Key Components -1. **AI Integration**: The contract uses `gl.exec_prompt()` to interact with an AI model. -2. **Deterministic Execution**: `gl.eq_principle_strict_eq()` ensures that all nodes in the network arrive at the same exact result. +1. **AI Integration**: The contract uses `gl.nondet.exec_prompt()` to interact with an AI model. +2. **Deterministic Execution**: `gl.eq_principle.strict_eq()` ensures that all nodes in the network arrive at the same exact result. 3. **State Management**: The contract maintains a single string state variable that stores the AI response. ## Deploying the Contract diff --git a/pages/developers/intelligent-contracts/examples/prediction.mdx b/pages/developers/intelligent-contracts/examples/prediction.mdx index 379680871..e381910e5 100644 --- a/pages/developers/intelligent-contracts/examples/prediction.mdx +++ b/pages/developers/intelligent-contracts/examples/prediction.mdx @@ -3,7 +3,7 @@ The Prediction Market contract sets up a scenario to determine the outcome of a football game between two teams. The contract uses the Equivalence Principle to ensure accurate and consistent decision-making based on the game's resolution data. ```python filename="PredictionMarket" copy -# { "Depends": "py-genlayer:test" } +# { "Depends": "py-genlayer:latest" } from genlayer import * @@ -13,34 +13,21 @@ import typing class PredictionMarket(gl.Contract): has_resolved: bool - game_date: str team1: str team2: str resolution_url: str + winner: u256 + score: str def __init__(self, game_date: str, team1: str, team2: str): - """ - Initializes a new instance of the prediction market with the specified game date and teams. - - Args: - game_date (str): The date of the game in the format 'YYYY-MM-DD'. - team1 (str): The name of the first team. - team2 (str): The name of the second team. - - Attributes: - has_resolved (bool): Indicates whether the game's resolution has been processed. Default is False. - game_date (str): The date of the game. - resolution_url (str): The URL to the game's resolution on BBC Sport. - team1 (str): The name of the first team. - team2 (str): The name of the second team. - """ self.has_resolved = False - self.game_date = game_date self.resolution_url = ( "https://www.bbc.com/sport/football/scores-fixtures/" + game_date ) self.team1 = team1 self.team2 = team2 + self.winner = u256(0) + self.score = "" @gl.public.write def resolve(self) -> typing.Any: @@ -48,36 +35,43 @@ class PredictionMarket(gl.Contract): if self.has_resolved: return "Already resolved" - def nondet() -> str: - web_data = gl.get_webpage(self.resolution_url, mode="text") + market_resolution_url = self.resolution_url + team1 = self.team1 + team2 = self.team2 + + def get_match_result() -> typing.Any: + web_data = gl.nondet.web.render(market_resolution_url, mode="text") print(web_data) - task = f"""In the following web page, find the winning team in a matchup between the following teams: - Team 1: {self.team1} - Team 2: {self.team2} - - Web page content: - {web_data} - End of web page data. - - If it says "Kick off [time]" between the names of the two teams, it means the game hasn't started yet. - If you fail to extract the score, assume the game is not resolved yet. - - Respond with the following JSON format: - {{ - "score": str, // The score with numbers only, e.g, "1:2", or "-" if the game is not resolved yet - "winner": int, // The number of the winning team, 0 for draw, or -1 if the game is not yet finished - }} - It is mandatory that you respond only using the JSON format above, - nothing else. Don't include any other words or characters, - your output must be only JSON without any formatting prefix or suffix. - This result should be perfectly parsable by a JSON parser without errors. + task = f""" +In the following web page, find the winning team in a matchup between the following teams: +Team 1: {team1} +Team 2: {team2} + +Web page content: +{web_data} +End of web page data. + +If it says "Kick off [time]" between the names of the two teams, it means the game hasn't started yet. +If you fail to extract the score, assume the game is not resolved yet. + +Respond with the following JSON format: +{{ + "score": str, // The score with numbers only, e.g, "1:2", or "-" if the game is not resolved yet + "winner": int, // The number of the winning team, 0 for draw, or -1 if the game is not yet finished +}} +It is mandatory that you respond only using the JSON format above, +nothing else. Don't include any other words or characters, +your output must be only JSON without any formatting prefix or suffix. +This result should be perfectly parsable by a JSON parser without errors. """ - result = gl.exec_prompt(task).replace("```json", "").replace("```", "") + result = ( + gl.nondet.exec_prompt(task).replace("```json", "").replace("```", "") + ) print(result) - return json.dumps(json.loads(result), sort_keys=True) + return json.loads(result) - result_json = json.loads(gl.eq_principle_strict_eq(nondet)) + result_json = gl.eq_principle.strict_eq(get_match_result) if result_json["winner"] > -1: self.has_resolved = True @@ -85,9 +79,17 @@ class PredictionMarket(gl.Contract): self.score = result_json["score"] return result_json + + @gl.public.view + def get_resolution_data(self) -> dict[str, typing.Any]: + return { + "winner": self.winner, + "score": self.score, + "has_resolved": self.has_resolved, + } ``` -You can check out this code on our [GitHub](https://github.com/genlayerlabs/genlayer-studio/blob/main/examples/contracts/football_prediction_market.py) +You can check out this code on our [GitHub](https://github.com/genlayerlabs/genlayer-testing-suite/blob/main/tests/examples/contracts/football_prediction_market.py) ## Deploying the Contract diff --git a/pages/developers/intelligent-contracts/examples/user-storage.mdx b/pages/developers/intelligent-contracts/examples/user-storage.mdx index 91f07ce34..3c9d3e094 100644 --- a/pages/developers/intelligent-contracts/examples/user-storage.mdx +++ b/pages/developers/intelligent-contracts/examples/user-storage.mdx @@ -35,7 +35,7 @@ class UserStorage(gl.Contract): - **Read Methods**: - `get_complete_storage()` returns the entire storage dictionary, containing all user data. - `get_account_storage(account_address)` returns the stored value for a specific user account. -- **Write Method**: `update_storage(new_storage)` allows updating the stored value for the user who called the contract (identified by `contract_runner.from_address`). +- **Write Method**: `update_storage(new_storage)` allows updating the stored value for the user who called the contract (identified by `gl.message.sender_address`). ## Deploying the Contract @@ -58,7 +58,7 @@ To interact with the deployed contract, go to the **Write Methods** section. Her When the `update_storage` method is executed: -- The contract updates the `self.storage` dictionary, associating the new value with the address of the user who called the function (`contract_runner.from_address`). +- The contract updates the `self.storage` dictionary, associating the new value with the address of the user who called the function (`gl.message.sender_address`). - You can then use the `get_account_storage()` or `get_complete_storage()` methods to verify that the value has been updated for the specific user. ## Handling Different Scenarios diff --git a/pages/developers/intelligent-contracts/examples/wizard-of-coin.mdx b/pages/developers/intelligent-contracts/examples/wizard-of-coin.mdx index bc2429851..3d33fbe4c 100644 --- a/pages/developers/intelligent-contracts/examples/wizard-of-coin.mdx +++ b/pages/developers/intelligent-contracts/examples/wizard-of-coin.mdx @@ -3,7 +3,7 @@ The Wizard of Coin contract sets up a scenario where a wizard possesses a valuable coin, which adventurers try to obtain. The wizard must decide whether to give the coin away based on specific conditions. ```python -# { "Depends": "py-genlayer:test" } +# { "Depends": "py-genlayer:latest" } from genlayer import * import json @@ -19,6 +19,7 @@ class WizardOfCoin(gl.Contract): def ask_for_coin(self, request: str) -> None: if not self.have_coin: return + prompt = f""" You are a wizard, and you hold a magical coin. Many adventurers will come and try to get you to give them the coin. @@ -42,23 +43,25 @@ your output must be only JSON without any formatting prefix or suffix. This result should be perfectly parseable by a JSON parser without errors. """ - def nondet(): - res = gl.exec_prompt(prompt) - res = res.replace("```json", "").replace("```", "") - print(res) - dat = json.loads(res) - return dat["give_coin"] + def get_wizard_answer(): + result = gl.nondet.exec_prompt(prompt) + result = result.replace("```json", "").replace("```", "") + print(result) + return result - result = gl.eq_principle_strict_eq(nondet) - assert isinstance(result, bool) - self.have_coin = result + result = gl.eq_principle.prompt_comparative( + get_wizard_answer, "The value of give_coin has to match" + ) + parsed_result = json.loads(result) + assert isinstance(parsed_result["give_coin"], bool) + self.have_coin = not parsed_result["give_coin"] @gl.public.view def get_have_coin(self) -> bool: return self.have_coin ``` -You can check out this code on our [GitHub](https://github.com/genlayerlabs/genlayer-studio/blob/main/examples/contracts/wizard_of_coin.py) +You can check out this code on our [GitHub](https://github.com/genlayerlabs/genlayer-testing-suite/blob/main/tests/examples/contracts/wizard_of_coin.py) ## Deploying the Contract diff --git a/pages/developers/intelligent-contracts/features/special-methods.mdx b/pages/developers/intelligent-contracts/features/special-methods.mdx index 03b53014b..1e65af201 100644 --- a/pages/developers/intelligent-contracts/features/special-methods.mdx +++ b/pages/developers/intelligent-contracts/features/special-methods.mdx @@ -42,7 +42,7 @@ graph TD fallback_is_payable -->|yes| fallback1{{call __handle_undefined_method__}} fallback_is_payable -->|no| error1{{error}} - has_value -->|no| fallback_defined + has_value -->|no| fallback_defined[is __handle_undefined_method__ defined?] fallback_defined -->|yes| fallback2{{call __handle_undefined_method__}} fallback_defined -->|no| error2{{error}} ``` diff --git a/pages/developers/intelligent-contracts/features/vector-storage.mdx b/pages/developers/intelligent-contracts/features/vector-storage.mdx index 5c412c838..eb2df0979 100644 --- a/pages/developers/intelligent-contracts/features/vector-storage.mdx +++ b/pages/developers/intelligent-contracts/features/vector-storage.mdx @@ -19,15 +19,11 @@ The Vector Store provides standard CRUD (Create, Read, Update, Delete) operation ## How to Use Vector Store in Your Contracts To use the Vector Store in your Intelligent Contracts, you will interact with its methods to add and retrieve text data, calculate similarities, and manage vector storage. Below are the details of how to use this feature. -#### Importing Vector Store -First, import the VectorStore class from the standard library in your contract: - -```python -from backend.node.genvm.std.vector_store import VectorStore -``` +#### Using VecDB in Your Contract +The `VecDB` type is available through the `genlayer` package. Import it with `from genlayer import *` along with other GenLayer types. #### Creating a Contract with Vector Store -Here’s an example of a contract using the Vector Store for indexing and searching text logs: +Here’s an example of a contract using `VecDB` for indexing and searching text logs: ```python # { diff --git a/pages/validators/setup-guide.mdx b/pages/validators/setup-guide.mdx index a1288eb3e..f5e5ec908 100644 --- a/pages/validators/setup-guide.mdx +++ b/pages/validators/setup-guide.mdx @@ -225,12 +225,12 @@ One full node can be shared between multiple validators. The optimal validator-t 3. Extract the node software ```sh copy mkdir -p ${version} - tar -xzvf `genlayer-node-linux-amd64-${version}.tar.gz` -C `./${version}` + tar -xzvf genlayer-node-linux-amd64-${version}.tar.gz -C ./${version} ``` 4. Change the directory ```sh copy - cd `./${version}` + cd ./${version} ``` 5. Run Genvm setup @@ -382,8 +382,7 @@ Any configuration value in `config.yaml` can be overridden using environment var |------------|---------------------| | `rollup.genlayerchainrpcurl` | `GENLAYERNODE_ROLLUP_GENLAYERCHAINRPCURL` | | `rollup.genlayerchainwebsocketurl` | `GENLAYERNODE_ROLLUP_GENLAYERCHAINWEBSOCKETURL` | -| `consensus.contractmainaddress` | `GENLAYERNODE_CONSENSUS_CONTRACTMAINADDRESS` | -| `consensus.contractdataaddress` | `GENLAYERNODE_CONSENSUS_CONTRACTDATAADDRESS` | +| `consensus.consensusaddress` | `GENLAYERNODE_CONSENSUS_CONSENSUSADDRESS` | | `consensus.genesis` | `GENLAYERNODE_CONSENSUS_GENESIS` | | `node.mode` | `GENLAYERNODE_NODE_MODE` | | `node.validatorWalletAddress` | `GENLAYERNODE_NODE_VALIDATORWALLETADDRESS` | @@ -394,8 +393,8 @@ Any configuration value in `config.yaml` can be overridden using environment var **Usage example:** ```sh copy -# Override the RPC port -export GENLAYERNODE_CONSENSUS_CONTRACTMAINADDRESS="0x..." +# Override the consensus address +export GENLAYERNODE_CONSENSUS_CONSENSUSADDRESS="0x..." # Set validator wallet address export GENLAYERNODE_NODE_VALIDATORWALLETADDRESS="0x..." @@ -520,14 +519,14 @@ Once you have configured everything, you are ready to start the node. ``` 3. (Optional) Run two services (modules) in background (this is a crucial step for running _Intelligent_ contracts). This can be done automatically or manually. - - To start them automatically in node configuration set `genvm.manage_modules` to `true` + - To start them automatically in node configuration set `genvm.start_manager` to `true` - To start them manually run ```bash copy ./third_party/genvm/bin/genvm-modules web & ./third_party/genvm/bin/genvm-modules llm & ``` - Note: If you are using the default configuration, `genvm.manage_modules` is + Note: If you are using the default configuration, `genvm.start_manager` is set to `true` by default, meaning the node will manage these modules automatically. @@ -649,7 +648,7 @@ WEBDRIVER_PORT=4444 # Node Service Configuration (optional - use node profile) # ============================================================================= # Docker image version -NODE_VERSION=v0.4.0 +NODE_VERSION=v0.5.1 # Keystore password (used to unlock the pre-imported wallet) NODE_PASSWORD=12345678 @@ -666,6 +665,8 @@ NODE_OPS_PORT=9153 # LLM API Key (required for GenVM LLM module) HEURISTKEY= +COMPUT3KEY= +IOINTELLIGENCE_API_KEY= ANTHROPICKEY= XAIKEY= GEMINIKEY= @@ -681,7 +682,7 @@ To ensure your node is correctly configured, you can run the following command: ```sh copy source .env && docker run --rm --env-file ./.env \ -v ${NODE_CONFIG_PATH:-./configs/node/config.yaml}:/app/configs/node/config.yaml \ - yeagerai/genlayer-node:${NODE_VERSION:-v0.4.0} \ + yeagerai/genlayer-node:${NODE_VERSION:-v0.5.1} \ ./bin/genlayernode doctor ```