-
Notifications
You must be signed in to change notification settings - Fork 3
chore: update contract feature docs #317
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| { | ||
| "features": "Features", | ||
| "storage": "Storage", | ||
| "error-handling": "Error Handling", | ||
| "upgradability": "Upgradability", | ||
| "balances": "Balances", | ||
| "interacting-with-intelligent-contracts": "Interacting with Intelligent Contracts", | ||
| "interacting-with-evm-contracts": "Interacting with EVM Contracts", | ||
| "vector-storage": "Vector Storage", | ||
| "debugging": "Debugging", | ||
| "special-methods": "Special Methods", | ||
| "random": "Random", | ||
| "non-determinism": "Non-determinism", | ||
| "calling-llms": "Calling LLMs", | ||
| "web-access": "Web Access" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import { Callout } from "nextra-theme-docs"; | ||
|
|
||
| # Balances | ||
|
|
||
| ## Getting Contract Balance | ||
|
|
||
| Access your contract's balance using `self.balance` within contract methods: | ||
|
|
||
| ```python | ||
| class Contract(gl.Contract): | ||
| @gl.public.view | ||
| def get_balance(self): | ||
| return self.balance # Shows contract's current balance | ||
| ``` | ||
|
|
||
| ## Getting Another Contract's Balance | ||
|
|
||
| Get any contract's balance by address: | ||
|
|
||
| ```python | ||
| other_contract = gl.get_contract_at(contract_address) | ||
| print(other_contract.balance) | ||
| ``` | ||
|
|
||
| ## Transferring Funds | ||
|
|
||
| Transfer funds from sender to current contract: | ||
|
|
||
| ```python | ||
| other_contract = gl.get_contract_at(gl.message.sender_address) | ||
| other_contract.emit_transfer(value=u256(5)) | ||
| other_contract.emit(value=u256(5), on='finalized').transfer(Address("0x...")) | ||
| ``` | ||
|
|
||
| ## Balance Context | ||
|
|
||
| Balance behavior depends on execution context: | ||
| - In `write` methods: `self.balance` reflects actual contract balance after state changes | ||
| - In `view` methods: Balance shows current state without modifications | ||
| - Transfers can only occur in write context | ||
|
|
||
| <Callout type="warning"> | ||
| If message is emitted on acceptance and previous transaction gets successfully appealed after the emit, | ||
| the balance will be decremented nonetheless | ||
| </Callout> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| import { Callout } from 'nextra-theme-docs' | ||
|
|
||
| # Calling LLMs | ||
|
|
||
| ## Basic LLM Calls | ||
|
|
||
| Execute prompts using large language models: | ||
|
|
||
| ```python | ||
| def llm_call(): | ||
| response = gl.nondet.exec_prompt("Answer this question") | ||
| return response.strip().lower() | ||
|
|
||
| # Consensus ensures consistent LLM responses | ||
| answer = gl.eq_principle.strict_eq(llm_call) | ||
| ``` | ||
|
|
||
| ## JSON Response Format | ||
|
|
||
| Request structured responses from LLMs: | ||
|
|
||
| ```python | ||
| def structured_llm_call(): | ||
| prompt = """ | ||
| Return a JSON object with these keys: | ||
| - "score": random integer from 1 to 100 | ||
| - "status": either "active" or "inactive" | ||
| """ | ||
| return gl.nondet.exec_prompt(prompt, response_format='json') | ||
|
|
||
| result = gl.eq_principle.strict_eq(structured_llm_call) | ||
| score = result['score'] # Access JSON fields | ||
| ``` | ||
|
|
||
| This approach guarantees that `exec_prompt` returns a valid JSON object, however | ||
| correspondence to the specified format depends on the underlying LLM. | ||
|
|
||
|
Comment on lines
+18
to
+37
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make JSON expectations explicit (avoid implying schema validation). def validated_call():
response = gl.nondet.exec_prompt(
- "Generate a number between 1 and 100",
+ 'Return JSON like {"number": <integer 1..100>}. Only return JSON.',
response_format='json'
)
# Validate the response
- if response['number'] < 1 or response['number'] > 100:
- raise Exception(f"Invalid number: {response['number']}")
+ number = response.get("number")
+ if not isinstance(number, int) or number < 1 or number > 100:
+ raise ValueError(f"Invalid number: {number!r}")
- return response['number']
+ return numberAlso applies to: 54-72 |
||
| ## Image Processing | ||
|
|
||
| Process images with vision models: | ||
|
|
||
| ```python | ||
| def vision_analysis(): | ||
| prompt = "Describe what you see in this image" | ||
| image_data = b"\x89PNG..." | ||
| return gl.nondet.exec_prompt( | ||
| prompt, | ||
| images=[image_data] | ||
| ) | ||
|
|
||
| description = gl.eq_principle.strict_eq(vision_analysis) | ||
| ``` | ||
|
|
||
| <Callout type="warning"> | ||
| Limit of images is two | ||
| </Callout> | ||
|
|
||
|
|
||
|
Comment on lines
42
to
58
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix broken Python snippet ( def vision_analysis():
prompt = "Describe what you see in this image"
- image_data = b"\x89PNG...'
+ image_data = b"\x89PNG..."
return gl.nondet.exec_prompt(
prompt,
images=[image_data]
)🤖 Prompt for AI Agents |
||
| ## Response Validation | ||
|
|
||
| Validate and process LLM responses: | ||
|
|
||
| ```python | ||
| def validated_call(): | ||
| response = gl.nondet.exec_prompt( | ||
| "Generate a number between 1 and 100", | ||
| response_format='json' | ||
| ) | ||
|
|
||
| # Validate the response | ||
| if response['number'] < 1 or response['number'] > 100: | ||
| raise Exception(f"Invalid number: {response['number']}") | ||
|
|
||
| return response['number'] | ||
|
|
||
| result = gl.eq_principle.strict_eq(validated_call) | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import { Callout } from "nextra-theme-docs"; | ||
|
|
||
| # Debugging | ||
|
|
||
| ## Print Statements | ||
|
|
||
| Use `print` calls for basic debugging, which will be present in node or studio output. | ||
|
|
||
| Use `gl.trace` to include time stamps in the output (it will be written to genvm_log instead of stdout) | ||
|
|
||
| ## Profiling | ||
|
|
||
| There is also `gl.trace_time_micro` which returns timestamp in the GenVM debug mode. Default bootloader includes | ||
| possibility to enable profiling by setting environment variable `GENLAYER_ENABLE_PROFILER=true`. | ||
|
|
||
| ```python | ||
| # { | ||
| # "Seq": [ | ||
| # { "SetEnv": { "name": "GENLAYER_ENABLE_PROFILER", "value": "true" } }, | ||
| # { "Depends": "py-genlayer:test" } | ||
| # ] | ||
| # } | ||
| ``` | ||
|
|
||
| This will output base-64 encoded gzip-compressed profiling data to stderr after every single VM execution | ||
|
|
||
| ## Attaching a Debugger | ||
|
|
||
| <Callout type="warning" emoji="🏗️"> | ||
| Unfortunately, attaching a debugger to a running Intelligent Contract is not supported yet | ||
| </Callout> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
GenLayer GenVM intelligent contract transfer funds emit_transfer API💡 Result:
Short answer
Minimal example (Python Intelligent Contract)
from genlayer import *
class Sender(gl.Contract):
@gl.public.write
def pay(self, to: Address, amount: int):
gl.ContractAt(to).emit_transfer(value=amount)
from genlayer import *
class Receiver(gl.Contract):
def receive(self):
# called when contract receives a nameless transfer
payer = gl.message.sender
amt = gl.message.value
# handle funds...
Key notes
Sources
[1] GenLayer — Working With Balances (emit_transfer, payable, receive).
[2] GenLayer SDK — gl.ContractAt and emit_transfer API.
[3] GenLayer Docs — Your First Contract (decorators, payable usage).
🌐 Web query:
GenLayer finalized vs accepted contract event emission semantics💡 Result:
Short answer — Accepted = tentative; Finalized = irreversible.
"Accepted" means validators reached majority but the finality/appeal window is still open. State and logs at Accepted can be appealed/recomputed and therefore may be be rolled back or changed. Use Accepted if you need faster, optimistic visibility but can tolerate reversions. [1][2][3]
"Finalized" means the appeal window passed (or fast-finality paid) and the transaction is immutable — contract state, messages and any durable outputs are permanent. Emit events/messages only when you require irreversible guarantees. [2][3]
GenLayer supports message-based contract-to-contract writes and lets developers choose when a message is emitted; messages emitted as part of an Accepted-state execution can be subject to appeals, while messages/emissions tied to Finalized state are non-reversible. For cross-contract interaction the docs explicitly point out message emission semantics to avoid cascading rollbacks. [4][2]
If you want, tell me which event/message in your contract you plan to emit and I’ll advise whether to emit at Accepted (optimistic, faster) or wait for Finalized (durable, safe), and show code examples. [1][2][3][4]
Sources:
Code snippet has two issues: incorrect transfer API syntax and misleading warning semantics.
The
.emit(..., on='finalized').transfer(...)pattern is not part of the documented GenLayer API. Use the canonicalemit_transfer(value=...)method only. Additionally:on='finalized'; these are contradictory. Transfers emitted during Accepted state can be appealed/rolled back; Finalized emissions are irreversible. Clarify which context applies and align the warning accordingly.🤖 Prompt for AI Agents