Endpoints and Functions
Endpoints are the externally callable entry points of a Coco logic, while functions are local helpers you call from endpoints. Endpoints define named inputs and named return values, and may be marked dynamic when they mutate state (any block that uses mutate must be in a dynamic endpoint). Special qualifiers deploy and enlist handle one-time logic initialization and per-actor initialization, respectively. Aside from visibility and these qualifiers, endpoint and function syntax is the same; Coco favors explicit, named arguments and returns for clarity and auditability.
coco Functions
endpoint Combine(x,y String) -> (z String):
memory w = join(y, (output) <- DoSomething())
yield z join(x, w)
function DoSomething() -> (output String):
yield output "done!"
Endpoint Syntax
An endpoint
in Coco is a callable element that can be invoked ("called") on the blockchain. A single endpoint is expected to perform simple and singular operations.
An endpoint can accept zero or more arguments and return some outputs. All arguments and return variables for an endpoint must be named. All return variables of the endpoint are automatically initialized at the beginning of its execution. See Functions.DoSomething()
Some endpoint names have a dynamic keyword. This is intended to emphasize that the endpoint modifies the state of the module. It is mandatory for any endpoint that uses the mutate keyword in its block. See TokenLedger.SeedSupply()
If multiple consecutive endpoint parameters are of the same data type, the type can be omitted from all but the last parameter.
Functions
function
keyword is used for callables that can only be called from endpoints locally. They
can't be invoked on the blockchain. On the other hand, endpoint can't invoke another endpoint,
so function
is a conventional reusable encapsulation of some functionality. So the difference between endpoint
and function
is just their visibility (endpoints can be called from blockchain and function from endpoints), everything else in the syntax is the same.
Arguments and return values
While passing arguments to and returning the return values from endpoints or functions in Coco is done in the same way as in most other programming languages, Coco requires a more verbose syntax for calling functions - namely, function call needs to include all argument and return value names. These names can only be omitted in case the argument has exactly the same name as the variable, so we can omit the name to avoid stuttering.
coco FCall
endpoint A():
memory x = (out) <- Double(num: 10)
memory num = 20
memory out = Double(num) // compared to the first line, we can omit names when variable names match
memory a, b = (x, y) <- Pair()
function Double(num U64) -> (out U64):
out = num * 2
function Pair() -> (x, y U64):
x, y = 3, 4
There's another strict rule regarding arguments and return values: arguments are read-only and return values are write-only. E.g., these things are not allowed:
function X(a, b U64) -> (out U64):
a += 1 // can't assign to an argument
out = a + b
out += 1 // this is "out = out + 1" and we can't read `out` at the right hand side
Deploy and Enlist
Every endpoint can get invoked, but two special qualifiers are available for deploying and enlisting. deploy
endpoint is used when the logic is first deployed on the blockchain and it initializes the logic's state. If there's no state logic
in the logic, deploy
endpoints are not needed.
When we have state actor
we can have enlist
endpoints that initialize actor's state.
deploy
endpoint can be called only once at deployment of the logic, while there's no limit for other endpoints (including enlist
).