-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstart.py
385 lines (297 loc) · 11.5 KB
/
start.py
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
import base64
from algosdk.future import transaction
from algosdk import account, mnemonic
from algosdk.v2client import algod
from pyteal import compileTeal, Mode
from asset import approval_program, clear_state_program
#DJ24DOMQY6GWI4NY6CFSQFNWREIQYTN6ABQU7DTIBY5KTGGENF3F2RSMJU
user_mnemonic = "input manage barrel job dizzy raise engine canvas metal novel pudding observe disagree advance rapid angry alert season seek dice system acoustic phone absent butter"
#TQSYJU6BRS4ECUTREW6WAVMRK6MR2XAOC6TKQ46QSDQLVXQJE2O3TT63AU
creator_mnemonic = "woman series evolve retreat alley update afford loop oven royal city bulk false chase arrow guess hood blade room year flower type ivory about daughter"
algod_address = "http://localhost:4001"
algod_token = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
algod_client = algod.AlgodClient(algod_token, algod_address)
# helper function to compile program source
def compile_program(client, source_code):
compile_response = client.compile(source_code)
return base64.b64decode(compile_response["result"])
# helper function that converts a mnemonic passphrase into a private signing key
def get_private_key_from_mnemonic(mn):
private_key = mnemonic.to_private_key(mn)
return private_key
def format_state(state):
formatted = {}
for item in state:
key = item["key"]
value = item["value"]
formatted_key = base64.b64decode(key).decode("utf-8")
if value["type"] == 1:
formatted[formatted_key] = value["bytes"]
else:
formatted[formatted_key] = value["uint"]
return formatted
# helper function that waits for a given txid to be confirmed by the network
def wait_for_confirmation(client, txid):
last_round = client.status().get("last-round")
txinfo = client.pending_transaction_info(txid)
while not (txinfo.get("confirmed-round") and txinfo.get("confirmed-round") > 0):
print("Waiting for confirmation...")
last_round += 1
client.status_after_block(last_round)
txinfo = client.pending_transaction_info(txid)
print(
"Transaction {} confirmed in round {}.".format(
txid, txinfo.get("confirmed-round")
)
)
return txinfo
def wait_for_round(client, round):
last_round = client.status().get("last-round")
print(f"Waiting for round {round}")
while last_round < round:
last_round += 1
client.status_after_block(last_round)
print(f"Round {last_round}")
# create new application
def create_app(
client,
private_key,
approval_program,
clear_program,
global_schema,
local_schema,
app_args,
foreign_assets
):
# define sender as creator
sender = account.address_from_private_key(private_key)
# declare on_complete as NoOp
on_complete = transaction.OnComplete.NoOpOC.real
# get node suggested parameters
params = client.suggested_params()
# comment out the next two (2) lines to use suggested fees
params.flat_fee = True
params.fee = 1000
# create unsigned transaction
txn = transaction.ApplicationCreateTxn(
sender = sender,
sp = params,
on_complete = on_complete,
approval_program = approval_program,
clear_program = clear_program,
global_schema = global_schema,
local_schema = local_schema,
app_args = app_args,
foreign_assets = foreign_assets
)
# sign transaction
signed_txn = txn.sign(private_key)
tx_id = signed_txn.transaction.get_txid()
# send transaction
client.send_transactions([signed_txn])
# await confirmation
wait_for_confirmation(client, tx_id)
# display results
transaction_response = client.pending_transaction_info(tx_id)
app_id = transaction_response["application-index"]
print("Created new app-id:", app_id)
return app_id
# opt-in to application
def opt_in_app(client, private_key, index):
# declare sender
sender = account.address_from_private_key(private_key)
print("OptIn from account: ", sender)
# get node suggested parameters
params = client.suggested_params()
# comment out the next two (2) lines to use suggested fees
params.flat_fee = True
params.fee = 1000
# create unsigned transaction
txn = transaction.ApplicationOptInTxn(sender, params, index)
# sign transaction
signed_txn = txn.sign(private_key)
tx_id = signed_txn.transaction.get_txid()
# send transaction
client.send_transactions([signed_txn])
# await confirmation
wait_for_confirmation(client, tx_id)
# display results
transaction_response = client.pending_transaction_info(tx_id)
print("OptIn to app-id:", transaction_response["txn"]["txn"]["apid"])
# call application
def call_app(client, private_key, index, app_args):
# declare sender
sender = account.address_from_private_key(private_key)
print("Call from account:", sender)
# get node suggested parameters
params = client.suggested_params()
# comment out the next two (2) lines to use suggested fees
params.flat_fee = True
params.fee = 1000
# create unsigned transaction
txn = transaction.ApplicationNoOpTxn(sender, params, index, app_args)
# sign transaction
signed_txn = txn.sign(private_key)
tx_id = signed_txn.transaction.get_txid()
# send transaction
client.send_transactions([signed_txn])
# await confirmation
wait_for_confirmation(client, tx_id)
# read user local state
def read_local_state(client, addr, app_id):
results = client.account_info(addr)
for local_state in results["apps-local-state"]:
if local_state["id"] == app_id:
if "key-value" not in local_state:
return {}
return format_state(local_state["key-value"])
return {}
# read app global state
def read_global_state(client, addr, app_id):
results = client.account_info(addr)
apps_created = results["created-apps"]
for app in apps_created:
if app["id"] == app_id:
return format_state(app["params"]["global-state"])
return {}
# delete application
def delete_app(client, private_key, index):
# declare sender
sender = account.address_from_private_key(private_key)
# get node suggested parameters
params = client.suggested_params()
# comment out the next two (2) lines to use suggested fees
params.flat_fee = True
params.fee = 1000
# create unsigned transaction
txn = transaction.ApplicationDeleteTxn(sender, params, index)
# sign transaction
signed_txn = txn.sign(private_key)
tx_id = signed_txn.transaction.get_txid()
# send transaction
client.send_transactions([signed_txn])
# await confirmation
wait_for_confirmation(client, tx_id)
# display results
transaction_response = client.pending_transaction_info(tx_id)
print("Deleted app-id:", transaction_response["txn"]["txn"]["apid"])
# close out from application
def close_out_app(client, private_key, index):
# declare sender
sender = account.address_from_private_key(private_key)
# get node suggested parameters
params = client.suggested_params()
# comment out the next two (2) lines to use suggested fees
params.flat_fee = True
params.fee = 1000
# create unsigned transaction
txn = transaction.ApplicationCloseOutTxn(sender, params, index)
# sign transaction
signed_txn = txn.sign(private_key)
tx_id = signed_txn.transaction.get_txid()
# send transaction
client.send_transactions([signed_txn])
# await confirmation
wait_for_confirmation(client, tx_id)
# display results
transaction_response = client.pending_transaction_info(tx_id)
print("Closed out from app-id: ", transaction_response["txn"]["txn"]["apid"])
# clear application
def clear_app(client, private_key, index):
# declare sender
sender = account.address_from_private_key(private_key)
# get node suggested parameters
params = client.suggested_params()
# comment out the next two (2) lines to use suggested fees
params.flat_fee = True
params.fee = 1000
# create unsigned transaction
txn = transaction.ApplicationClearStateTxn(sender, params, index)
# sign transaction
signed_txn = txn.sign(private_key)
tx_id = signed_txn.transaction.get_txid()
# send transaction
client.send_transactions([signed_txn])
# await confirmation
wait_for_confirmation(client, tx_id)
# display results
transaction_response = client.pending_transaction_info(tx_id)
print("Cleared app-id:", transaction_response["txn"]["txn"]["apid"])
# convert 64 bit integer i to byte string
def intToBytes(i):
return i.to_bytes(8, "big")
def main():
# initialize an algodClient
algod_client = algod.AlgodClient(algod_token, algod_address)
# define private keys
creator_private_key = get_private_key_from_mnemonic(creator_mnemonic)
user_private_key = get_private_key_from_mnemonic(user_mnemonic)
# declare application state storage (immutable)
local_ints = 2
local_bytes = 0
global_ints = 2
global_bytes = 1
global_schema = transaction.StateSchema(global_ints, global_bytes)
local_schema = transaction.StateSchema(local_ints, local_bytes)
# get PyTeal approval program
approval_program_ast = approval_program()
# compile program to TEAL assembly
approval_program_teal = compileTeal(approval_program_ast, mode=Mode.Application, version=5)
# compile program to binary
approval_program_compiled = compile_program(algod_client, approval_program_teal)
# get PyTeal clear state program
clear_state_program_ast = clear_state_program()
# compile program to TEAL assembly
clear_state_program_teal = compileTeal(clear_state_program_ast, mode=Mode.Application, version=5)
# compile program to binary
clear_state_program_compiled = compile_program(algod_client, clear_state_program_teal)
# create list of bytes for app args
app_args = [
intToBytes(1000),
]
app_assets = [
intToBytes(174), intToBytes(177),
]
# create new application
app_id = create_app(
algod_client,
creator_private_key,
approval_program_compiled,
clear_state_program_compiled,
global_schema,
local_schema,
app_args,
#app_assets
[174]
)
# read global state of application
print(
"Global state:",
read_global_state(
algod_client, account.address_from_private_key(creator_private_key), app_id
),
)
# opt-in to application creator and user
opt_in_app(algod_client, creator_private_key, app_id)
opt_in_app(algod_client, user_private_key, app_id)
# call application
call_app(algod_client, creator_private_key, app_id, [b"mint", intToBytes(10)])
call_app(algod_client, creator_private_key, app_id, [b"transfer", intToBytes(2)])
# read local state of application from user account
print(
"Local state:",
read_local_state(
algod_client, account.address_from_private_key(creator_private_key), app_id
),
)
# read global state of application
global_state = read_global_state(
algod_client, account.address_from_private_key(creator_private_key), app_id
)
print("Global state:", global_state)
# delete application
delete_app(algod_client, creator_private_key, app_id)
# clear application from user account
clear_app(algod_client, creator_private_key, app_id)
if __name__ == "__main__":
main()