-
Notifications
You must be signed in to change notification settings - Fork 4
docs: TEALScript migration guide #225
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
Draft
joe-p
wants to merge
32
commits into
main
Choose a base branch
from
docs/tealscript-migration
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 5 commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
a28ab78
wip: tealscript-migration.md
joe-p 7ca0de3
wip: itxn section
joe-p c5d0088
wip: events
joe-p 914f974
wip: compiled contract info
joe-p ac19606
wip: lsig
joe-p 365ffed
wip: template var
joe-p c25c963
wip: template vars
joe-p c4623e7
wip: numerical types and math
joe-p 43c8333
wip: box create
joe-p cc94038
wip: casting
joe-p 99b3fb5
wip: refs
joe-p 6d7ecea
wip: add summary to obj and array
joe-p 2e23aa7
wip: add globals
joe-p b348e92
wip: add StaticArray
joe-p adde4c1
wip: address some TODOs
joe-p 8514959
wip: dynamic types in objects
joe-p 6327c65
wip: nested dynamic arrays
joe-p 1473a66
wip: lsig arg
joe-p aeae5f4
wip: PR feedback
joe-p 7c775fd
wip: rm array/object migration
joe-p c5087dd
UintN -> Uint
joe-p 4b403b7
reference types
joe-p 9a72fb3
formatting and rm TODOs
joe-p 47d1d9c
bump ver
joe-p a15c64a
fix Address table
joe-p 4623d9a
rm old statement about ensted types
joe-p 9cea62e
rm ref type section
joe-p 8ff7542
update tmpl var section
joe-p a2c1b06
update uint section
joe-p 981184e
rename native
joe-p 2c12e5c
throw Error migration
joe-p 951d4a0
this.app
joe-p File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or 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,328 @@ | ||
| # TEALScript Migration Guide | ||
|
|
||
| This document is up-to-date as of TEALScript v0.107.0 and Algorand TypeScript v1.0.0-beta71 | ||
|
|
||
| ## Migration Table | ||
|
|
||
| | TEALScript | Algorand TypeScript | Notes | | ||
| | --- | --- | --- | | ||
| | JS Object | JS Object | Algorand TypeScript does not yet support nested dynamic types in JavaScript objects. TEALScript allows one level of nesting. For nested dynamic types, see [Objects](#objects) | | ||
| | JS Array | JS Array | Algorand TypeScript does not yet support nested dynamic types in JavaScript arrays. TEALScript allows one level ofnesting. For nested dynamic types, see [Arrays](#arrays) | | ||
| | `EventLogger` | [`emit`](https://dev.algorand.co/reference/algorand-typescript/api-reference/index/functions/emit) || | ||
| | `BoxKey` | [`Box`](TOOD: link to box docs) | The crate method has new parameters as shown [here](TODO: link to box section) | | ||
| | `Txn` | `Transaction` || | ||
| | `PayTxn` | `PaymentTxn` || | ||
| | `AppCallTxn` | `ApplicationCallTxn` || | ||
| | `KeyRegTxn` | `KeyRegistrationTxn` || | ||
| | `OnCompletion` | `OnCompleteAction` || | ||
| | Eliptic curve opcodes (i.e `ecAdd`) | Now under [`ElipticCurve`](TODO: link to EC docs) (i.e. `ElipticCurve.add`) || | ||
| | `GlobalStateKey` | `GlobalState` || | ||
| | `LocalStateKey` | `LocalState` || | ||
| | `GlobalStateMap` | Not yet supported || | ||
| | `LocalStateMap` | Not yet supported || | ||
| | `isOptedInToApp` and `isOptedInToAsset` | [`isOptedIn`](TODO: link to isOptedInDocs) || | ||
| | `this.txn` | [`Txn`](TOOD: link to Txn docs) || | ||
| | `verify...Txn` | `assertMatch` | `assertMatch` can be used on any txn type or any object || | ||
|
|
||
| ## Migrations | ||
|
|
||
| ### Objects | ||
|
|
||
| TODO: describe different types of objects and when you need to use them over POJOs | ||
|
|
||
| ### Arrays | ||
|
|
||
| TODO: describe different types of arrays and when you need to use them over native arrays | ||
joe-p marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ### Emitting Events | ||
|
|
||
| ##### TEALScript | ||
|
|
||
| ```ts | ||
| class Swapper | ||
| swap = new EventLogger<{ | ||
| assetA: AssetID; | ||
| assetB: AssetID; | ||
| }>(); | ||
|
|
||
| doSwap(a: AssetID, b: AssetID) { | ||
| this.swap.log({assetA: a, assetB: b}) | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ##### Algorand TypeScript | ||
|
|
||
| ```ts | ||
| type Swap = {assetA: uint64, assetB: uint64} | ||
|
|
||
| class Swapper | ||
| doSwap(a: uint64, b: uint64) { | ||
| emit('swap', {assetA: a, assetB: b} as Swap) | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| The event name can also be inferred from the name of a defined type | ||
|
|
||
| ```ts | ||
| type swap = {assetA: uint64, assetB: uint64} | ||
|
|
||
| class Swapper | ||
| doSwap(a: uint64, b: uint64) { | ||
| emit<swap>({assetA: a, assetB: b}) | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### Box Creation | ||
|
|
||
| TODO | ||
|
|
||
| ### Box Iteration | ||
|
|
||
| TODO: is this supported? | ||
|
|
||
| ### Inner Transactions | ||
|
|
||
| The interfaces for forming, sending, and inspecting inner transactions have significantly improved with Algorand TypeScript, but the | ||
| interfaces are quite different. They all revolve around the `itxn` namespace. | ||
|
|
||
| #### Sending a transaction | ||
|
|
||
| ##### TEALScript | ||
|
|
||
| ```ts | ||
| sendAssetConfig({ | ||
| total: 1000, | ||
| assetName: 'AST1', | ||
| unitName: 'unit' | ||
| decimals: 3, | ||
| manager: this.app.address, | ||
| reserve: this.app.address | ||
| }) | ||
| ``` | ||
|
|
||
| ##### Algorand TypeScript | ||
|
|
||
| ```ts | ||
| import { itxn, Global, log } from '@algorandfoundation/algorand-typescript' | ||
|
|
||
| const assetParams = itxn.assetConfig({ | ||
| total: 1000, | ||
| assetName: 'AST1', | ||
| unitName: 'unit', | ||
| decimals: 3, | ||
| manager: Global.currentApplicationAddress, | ||
| reserve: Global.currentApplicationAddress, | ||
| }) | ||
|
|
||
| const asset1_txn = assetParams.submit() | ||
| log(asset1_txn.createdAsset.id) | ||
| ``` | ||
|
|
||
| #### Sending a Transaction Group | ||
|
|
||
| ##### TEALScript | ||
|
|
||
| ```ts | ||
| this.pendingGroup.addAssetCreation({ | ||
| configAssetTotal: 1000, | ||
| configAssetName: this.name.value, | ||
| configAssetUnitName: 'unit', | ||
| configAssetDecimals: 3, | ||
| configAssetManager: this.app.address, | ||
| configAssetReserve: this.app.address, | ||
| }); | ||
|
|
||
| this.pendingGroup.addAppCall({ | ||
| approvalProgram: APPROVE, | ||
| clearStateProgram: APPROVE, | ||
| fee: 0, | ||
| }); | ||
|
|
||
| const appCreateTxn = this.lastInnerGroup[0]; | ||
| const asset3_txn = this.lastInnerGroup[1]; | ||
|
|
||
| assert(appCreateTxn.createdApplicationID, 'app is created'); | ||
| assert(asset3_txn.createdAssetID === 'AST3', 'asset3_txn is correct'); | ||
| ``` | ||
|
|
||
| ##### Algorand TypeScript | ||
|
|
||
| ```ts | ||
| const assetParams = itxn.assetConfig({ | ||
| total: 1000, | ||
| assetName: this.name.value, | ||
joe-p marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| unitName: 'unit', | ||
| decimals: 3, | ||
| manager: Global.currentApplicationAddress, | ||
| reserve: Global.currentApplicationAddress, | ||
| }) | ||
|
|
||
| const appCreateParams = itxn.applicationCall({ | ||
| approvalProgram: APPROVE, | ||
| clearStateProgram: APPROVE, | ||
| fee: 0, | ||
| }) | ||
|
|
||
| const [appCreateTxn, asset3_txn] = itxn.submitGroup(appCreateParams, assetParams) | ||
|
|
||
| assert(appCreateTxn.createdApp, 'app is created') | ||
| assert(asset3_txn.assetName === Bytes('AST3'), 'asset3_txn is correct') | ||
| ``` | ||
|
|
||
| #### Typed Method Calls | ||
|
|
||
| In Algorand TypeScript, there is a specific `abiCall` method for typed contract-to-contract calls instead of a generic like in TEALScript. | ||
|
|
||
| These examples are for calling a contract method with the signature `greet(name: string): string` in a contract `Hello` that returns `"hello " + name` | ||
|
|
||
| ##### TEALScript | ||
|
|
||
| ```ts | ||
| const result = sendMethodCall<typeof Hello.prototype.greet>({ | ||
| applicationID: app, | ||
| methodArgs: ['algo dev'], | ||
| }); | ||
|
|
||
| assert(result === 'hello algo dev') | ||
| ``` | ||
|
|
||
| ##### Algorand TypeScript | ||
|
|
||
| ```ts | ||
| const result = abiCall(Hello.prototype.greet, { | ||
| appId: app, | ||
| args: ['algo dev'], | ||
| }).returnValue | ||
| assert(result === 'hello algo dev') | ||
| ``` | ||
|
|
||
| #### App Creation | ||
|
|
||
| In Algorand TypeScript, you must first explicitly compile a contract before creating it or access the programs/schema | ||
|
|
||
| ##### TEALScript | ||
|
|
||
| ```ts | ||
| sendMethodCall<typeof Greeter.prototype.createApplication>({ | ||
| clearStateProgram: Greeter.clearProgram(), | ||
| approvalProgram: Greeter.approvalProgram(), | ||
| globalNumUint: Greeter.schema.global.numUint, | ||
| methodArgs: ['hello'], | ||
| }); | ||
|
|
||
| const app = this.itxn.createdApplicationId; | ||
|
|
||
| const result = sendMethodCall<typeof Greeter.prototype.greet>({ | ||
| applicationID: app, | ||
| methodArgs: ['world'], | ||
| }); | ||
|
|
||
| assert(result == 'hello world') | ||
| ``` | ||
|
|
||
| ##### Algorand TypeScript | ||
|
|
||
| ```ts | ||
| // First explicitly compile the app | ||
| const compiled = compileArc4(Greeter) | ||
|
|
||
| const app = compiled.call.createApplication({ | ||
| args: ['hello'], | ||
| globalNumUint: compiled.globalUints | ||
| }).itxn.createdApp | ||
|
|
||
| const result = compiled.call.greet({ | ||
| args: ['world'], | ||
| appId: app, | ||
| }).returnValue | ||
|
|
||
| assert(result === 'hello world') | ||
| ``` | ||
|
|
||
| ### Reference Types | ||
|
|
||
| TODO | ||
|
|
||
| ### Compiled Contract Information | ||
|
|
||
| TEALScript contracts have static methods for getting the contract programs and schema. In Algorand TypeScript, you must first explicitly | ||
| compile the contract and then use the resulting object to access program information. | ||
|
|
||
| ##### TEALScript | ||
|
|
||
| ```ts | ||
| // Access program information directly via static methods | ||
| sendMethodCall<typeof Greeter.prototype.createApplication>({ | ||
| clearStateProgram: Greeter.clearProgram(), | ||
| approvalProgram: Greeter.approvalProgram(), | ||
| globalNumUint: Greeter.schema.global.numUint, | ||
| methodArgs: ['hello'], | ||
| }); | ||
| ``` | ||
|
|
||
| ##### Algorand TypeScript | ||
|
|
||
| ```ts | ||
| // First explicitly compile the app | ||
| const compiled = compileArc4(Greeter) | ||
|
|
||
| // Then access program information on the compiled object | ||
| const app = compiled.call.createApplication({ | ||
| args: ['hello'], | ||
| globalNumUint: compiled.globalUints | ||
| }).itxn.createdApp | ||
| ``` | ||
|
|
||
| ### Logic Sigs | ||
|
|
||
| In TEALScript, logic sigs must implement the `logic` method which may take one or more arguments which map to the lsig arguments when | ||
| forming the transaction. All lsigs are approved unless an error occurs. Algorand TypeScript also requires implementation of the `program` method but it may not take an arguments and must return a `boolean` or `uint64` indicating whether the transaction is approved or not. | ||
|
|
||
| ##### TEALScript | ||
|
|
||
| ```ts | ||
| class DangerousPaymentLsig extends LogicSig { | ||
| logic(amt: uint64) { | ||
| assert(this.txn.amount === amt) | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ##### Algorand TypeScript | ||
|
|
||
| TODO: How do you get args? | ||
joe-p marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```ts | ||
| class DangerousPaymentLsig extends LogicSig { | ||
| program() { | ||
| return this.txn.amount === amt | ||
| } | ||
| } | ||
| ``` | ||
joe-p marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ### Template Variables | ||
|
|
||
| TODO | ||
|
|
||
| ### Importing | ||
|
|
||
| TODO | ||
|
|
||
| ### Numerical Types | ||
|
|
||
| TODO | ||
|
|
||
| ### Math and Overflows | ||
|
|
||
| TODO | ||
|
|
||
| ### Casting | ||
|
|
||
| TODO | ||
|
|
||
| ### Array & Object References | ||
|
|
||
| TODO | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.