-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathexample_const.py
More file actions
111 lines (93 loc) · 4.93 KB
/
example_const.py
File metadata and controls
111 lines (93 loc) · 4.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import pyteal as pt
import beaker as bk
import uuid
import base64
import re
import gora
class ExampleConstState:
last_oracle_value = bk.GlobalStateValue(
stack_type=pt.TealType.bytes,
descr="Last oracle value received"
)
example_const_app = bk.Application("ExampleConst", state=ExampleConstState)
# Opt in to Gora token asset, necessary to make oracle requests.
@example_const_app.external
def init_gora(token_ref: pt.abi.Asset, main_app_ref: pt.abi.Application):
return gora.pt_init_gora()
# Response handler.
@example_const_app.external
def handle_oracle_const(resp_type: pt.abi.Uint32,
resp_body_bytes: pt.abi.DynamicBytes):
return pt.Seq(
gora.pt_auth_dest_call(),
gora.pt_smart_assert(resp_type.get() == pt.Int(1)),
(resp_body := pt.abi.make(gora.ResponseBody)).decode(resp_body_bytes.get()),
resp_body.oracle_value.store_into(
oracle_value := pt.abi.make(pt.abi.DynamicBytes)
),
example_const_app.state.last_oracle_value.set(oracle_value.get())
)
# Query a test oracle source that always returns 1.
@example_const_app.external
def query_oracle_const(request_key: pt.abi.DynamicBytes) -> pt.Expr:
return pt.Seq(
# Type of oracle request, see Gora documentation for available types.
(request_type := pt.abi.Uint64()).set(pt.Int(1)),
# ID of the oracle source being queried. For this basic test, we are
# querying a special test source #1.
(source_id := pt.abi.Uint32()).set(pt.Int(1)),
# Arguments to pass to the source. This one takes no arguments.
(source_args := pt.abi.make(pt.abi.DynamicArray[pt.abi.DynamicBytes])).set([]),
# Maximum age in seconds an oracle source response can have before being
# discarded as outdated. Set to 0 if not using this feature.
(max_age := pt.abi.Uint32()).set(pt.Int(0)),
# Source specification is the structure combining the above elements.
(source_spec := pt.abi.make(gora.SourceSpec)).set(
source_id, source_args, max_age
),
# Source specification array needs to be built from it albeit with a
# single element because Gora supports multiple sources per request.
(source_spec_arr := pt.abi.make(pt.abi.DynamicArray[gora.SourceSpec])).set(
[ source_spec ]
),
# Result aggregation method. Set to 0 if unused, see Gora documentation
# for other valid values.
(aggr_method := pt.abi.Uint32()).set(pt.Int(0)),
# Arbitrary user-supplied byte string passed to the destination smart
# contract along with the response to this oracle request. Can be used,
# for example, to instruct the destination method on how to handle the
# response. To keep this example simple, we pass nothing.
(user_data := pt.abi.DynamicBytes()).set([]),
# Request specification is the structure describing an oracle request of
# the chosen type which we now build based on the data above. It then
# needs to be packed as bytes because specifications for different
# request types must be handled transparrently ABI type differences.
(request_spec := pt.abi.make(gora.RequestSpec)).set(
source_spec_arr, aggr_method, user_data
),
(request_spec_packed := pt.abi.DynamicBytes()).set(request_spec.encode()),
# Destination smart contract specification, consisting of its app ID and
# ABI method selector. For simplicity, we will use a method in this same
# app that makes the request, but it can be any smart contract app.
(dest_app_id := pt.abi.Uint64()).set(pt.Global.current_application_id()),
(dest_method_sig := pt.abi.DynamicBytes()).set(pt.Bytes("handle_oracle_const")),
(dest := pt.abi.make(gora.DestinationSpec)).set(dest_app_id, dest_method_sig),
(dest_packed := pt.abi.DynamicBytes()).set(dest.encode()),
# Algorand object references for Gora to include with call to the
# destination smart contract. In this basic case none are needed.
(asset_refs := pt.abi.make(pt.abi.DynamicArray[pt.abi.Uint64])).set([]),
(account_refs := pt.abi.make(pt.abi.DynamicArray[pt.abi.Address])).set([]),
(app_refs := pt.abi.make(pt.abi.DynamicArray[pt.abi.Uint64])).set([]),
(box_refs := pt.abi.make(pt.abi.DynamicArray[gora.BoxType])).set([]),
# Call Gora main smart contract and submit the oracle request.
pt.InnerTxnBuilder.Begin(),
pt.InnerTxnBuilder.MethodCall(
app_id=pt.Int(gora.main_app_info["id"]),
method_signature="request" + gora.request_method_spec,
args=[ request_spec_packed, dest_packed, request_type, request_key,
app_refs, asset_refs, account_refs, box_refs ],
),
pt.InnerTxnBuilder.Submit(),
)
if __name__ == "__main__":
gora.run_demo_app(example_const_app, query_oracle_const, True)