-
Notifications
You must be signed in to change notification settings - Fork 131
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initial commit * Fix abi-docs tests (#402) * Fix abi-docs Sphinx warnings (#401) * Extend abi-docs with experimental design language (#403) * Add type fundamentals section * Add basic type usage and some docstrings for referenced methods * Finish documenting set and fix overloaded method docs * Add docstrings for get and __getitem__ * Add reference type docs * Add txn type examples * Fix errors * Make ComputedValue parameter type covariant * ComputedValue and subroutine sections * ...wasn't included in previous commit * Add bare app call and method registration examples * Add router e2e example and compilation explanation * Fix post-merge linter/test failures * Add calling documentation * Partially address feedback * Respond to feedback * Resolve TODOs * Add pragma references * didn't make it into the previous commit * Fix Bool.__module__ * Mention stack size limit * More pragma documentation * Address other feedback * Warn about reference type limits * **cannot** Co-authored-by: Michael Diamant <michaeldiamant@users.noreply.github.com>
- Loading branch information
1 parent
281f2d3
commit 657064f
Showing
33 changed files
with
1,789 additions
and
194 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
{ | ||
"name": "AlgoBank", | ||
"methods": [ | ||
{ | ||
"name": "deposit", | ||
"args": [ | ||
{ | ||
"type": "pay", | ||
"name": "payment" | ||
}, | ||
{ | ||
"type": "account", | ||
"name": "sender" | ||
} | ||
], | ||
"returns": { | ||
"type": "void" | ||
}, | ||
"desc": "This method receives a payment from an account opted into this app and records it in their local state. The caller may opt into this app during this call." | ||
}, | ||
{ | ||
"name": "getBalance", | ||
"args": [ | ||
{ | ||
"type": "account", | ||
"name": "user" | ||
} | ||
], | ||
"returns": { | ||
"type": "uint64" | ||
}, | ||
"desc": "Lookup the balance of a user held by this app." | ||
}, | ||
{ | ||
"name": "withdraw", | ||
"args": [ | ||
{ | ||
"type": "uint64", | ||
"name": "amount" | ||
}, | ||
{ | ||
"type": "account", | ||
"name": "recipient" | ||
} | ||
], | ||
"returns": { | ||
"type": "void" | ||
}, | ||
"desc": "Withdraw an amount of Algos held by this app. The sender of this method call will be the source of the Algos, and the destination will be the `recipient` argument. This may or may not be the same as the sender's address. This method will fail if the amount of Algos requested to be withdrawn exceeds the amount of Algos held by this app for the sender. The Algos will be transferred to the recipient using an inner transaction whose fee is set to 0, meaning the caller's transaction must include a surplus fee to cover the inner transaction." | ||
} | ||
], | ||
"desc": null, | ||
"networks": {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
# This example is provided for informational purposes only and has not been audited for security. | ||
from pyteal import * | ||
import json | ||
|
||
|
||
@Subroutine(TealType.none) | ||
def assert_sender_is_creator() -> Expr: | ||
return Assert(Txn.sender() == Global.creator_address()) | ||
|
||
|
||
# move any balance that the user has into the "lost" amount when they close out or clear state | ||
transfer_balance_to_lost = App.globalPut( | ||
Bytes("lost"), | ||
App.globalGet(Bytes("lost")) + App.localGet(Txn.sender(), Bytes("balance")), | ||
) | ||
|
||
router = Router( | ||
name="AlgoBank", | ||
bare_calls=BareCallActions( | ||
# approve a creation no-op call | ||
no_op=OnCompleteAction(action=Approve(), call_config=CallConfig.CREATE), | ||
# approve opt-in calls during normal usage, and during creation as a convenience for the creator | ||
opt_in=OnCompleteAction(action=Approve(), call_config=CallConfig.ALL), | ||
# move any balance that the user has into the "lost" amount when they close out or clear state | ||
close_out=OnCompleteAction( | ||
action=transfer_balance_to_lost, call_config=CallConfig.CALL | ||
), | ||
clear_state=OnCompleteAction( | ||
action=transfer_balance_to_lost, call_config=CallConfig.CALL | ||
), | ||
# only the creator can update or delete the app | ||
update_application=OnCompleteAction( | ||
action=assert_sender_is_creator, call_config=CallConfig.CALL | ||
), | ||
delete_application=OnCompleteAction( | ||
action=assert_sender_is_creator, call_config=CallConfig.CALL | ||
), | ||
), | ||
) | ||
|
||
|
||
@router.method(no_op=CallConfig.CALL, opt_in=CallConfig.CALL) | ||
def deposit(payment: abi.PaymentTransaction, sender: abi.Account) -> Expr: | ||
"""This method receives a payment from an account opted into this app and records it in | ||
their local state. | ||
The caller may opt into this app during this call. | ||
""" | ||
return Seq( | ||
Assert(payment.get().sender() == sender.address()), | ||
Assert(payment.get().receiver() == Global.current_application_address()), | ||
App.localPut( | ||
sender.address(), | ||
Bytes("balance"), | ||
App.localGet(sender.address(), Bytes("balance")) + payment.get().amount(), | ||
), | ||
) | ||
|
||
|
||
@router.method | ||
def getBalance(user: abi.Account, *, output: abi.Uint64) -> Expr: | ||
"""Lookup the balance of a user held by this app.""" | ||
return output.set(App.localGet(user.address(), Bytes("balance"))) | ||
|
||
|
||
@router.method | ||
def withdraw(amount: abi.Uint64, recipient: abi.Account) -> Expr: | ||
"""Withdraw an amount of Algos held by this app. | ||
The sender of this method call will be the source of the Algos, and the destination will be | ||
the `recipient` argument. This may or may not be the same as the sender's address. | ||
This method will fail if the amount of Algos requested to be withdrawn exceeds the amount of | ||
Algos held by this app for the sender. | ||
The Algos will be transferred to the recipient using an inner transaction whose fee is set | ||
to 0, meaning the caller's transaction must include a surplus fee to cover the inner | ||
transaction. | ||
""" | ||
return Seq( | ||
# if amount is larger than App.localGet(Txn.sender(), Bytes("balance")), the subtraction | ||
# will underflow and fail this method call | ||
App.localPut( | ||
Txn.sender(), | ||
Bytes("balance"), | ||
App.localGet(Txn.sender(), Bytes("balance")) - amount.get(), | ||
), | ||
InnerTxnBuilder.Begin(), | ||
InnerTxnBuilder.SetFields( | ||
{ | ||
TxnField.type_enum: TxnType.Payment, | ||
TxnField.receiver: recipient.address(), | ||
TxnField.amount: amount.get(), | ||
TxnField.fee: Int(0), | ||
} | ||
), | ||
InnerTxnBuilder.Submit(), | ||
) | ||
|
||
|
||
approval_program, clear_state_program, contract = router.compile_program( | ||
version=6, optimize=OptimizeOptions(scratch_slots=True) | ||
) | ||
|
||
if __name__ == "__main__": | ||
with open("algobank_approval.teal", "w") as f: | ||
f.write(approval_program) | ||
|
||
with open("algobank_clear_state.teal", "w") as f: | ||
f.write(clear_state_program) | ||
|
||
with open("algobank.json", "w") as f: | ||
f.write(json.dumps(contract.dictify(), indent=4)) |
Oops, something went wrong.