But it seems that some docs are not up to date (about map() or events, for example), and I’m not sure about how much is implemented in the app https://contracts.aepps.com/
It also possible that my code is wrong, I don’t know, but can someone confirm that I can create events, and Map.lookup is a implemented function ?
Events are not yet merged (they’re in a PR now) as you can see in protocol/contracts/sophia.md#events. This repo is probably the best source of truth since the core developers that create Sophia, continuously update it.
What relates to github.com/aeternity/epoch/tree/master/apps/aesophia/test/contracts - there are a lot of different approaches for contract language design that had been tried out there. Most of those concepts had later on been refined in what currently Sophia is but some concepts had not yet made it in. So these are proto-contracts and some of them ado not compile at all. Please use them as a source of inspiration and not as a source of truth.
Hi @dimitar.chain
Thanks for your answer. It’s a little more clear for me.
Can you confirm me that uint are not yet implemented ? Some compilations didn’t worked for me with it ?
I tried to clean up my code, but now I don’t know if I’m wrong because of my lack of knowledge of Sophia of because I’m trying something not yet implemented.
Thanks to tell me if it’s better to create another topic instead of using this one, but can someone correct me this code ?
contract SomeToken =
type balances = map(address, int)
public function memberOf(owner : address) : int =
switch(Map.member(owner, balances))
true => balances[owner]
_ => 0
public function lookupOf(owner : address) : int =
switch(Map.lookup(owner, balances))
None => 0
Some(n) => n
I got a 403 : type_errors so I suppose it is Sophia grammar related…?
Main reason your contract does not compile is misunderstanding of types and state. You can have a lot of different types and records and play with those. Only one could represent your state but it can get as complex as you need it to be.
I took the liberty of refactoring your code a bit.
contract SomeToken =
type balances_t = map(address, int)
record state = { balances : balances_t }
public function init() : state =
{ balances = {}
}
public function memberOf(owner : address) : int =
switch(Map.member(owner, state.balances))
true => state.balances[owner]
_ => 0
public function lookupOf(owner : address) : int =
switch(Map.lookup(owner, state.balances))
None => 0
Some(n) => n
Main things changed:
Renamed the balances type to balances_t - this does not hold state, it is just an alias for the map(address, int)
type balances_t = map(address, int)
Created a new record to hold the state - state. It has a member balances of type balances_t that will hold all balances. You can extend the record to have other members as well. If you want to store something and later modify it or look it up - this is the place to add it.
record state = { balances : balances_t }
Introduced a public function init(). As described in the protocol - if you plan on having a state, you must have an init function. It can take any number of arguments but it must return the initial state. In the example bellow the initial balances map is empty.
public function init() : state =
{ balances = {}
}
Modified the functions to use the balances from the state (replaced balances with state.balances ). In your code you were looking up into the balances which used to be a type and this doesn’t make much sense as types are stateless. If you want to use a state - that’s what contract state is for.
At the moment please use int. The uint type still needs some polish
Haaaa ok, I totally missed the part type/state. Seems more clear now.
So if I have understood, when events will be available, I’ll have something like that :
type balances_t = map(address, int)
type canTransfer_e (e : event) = (address, int)
record state = { balances : balances_t, canTransfer : canTransfer_e }
public function init() : state =
{ balances = {}
}
public function memberOf(owner : address) : int =
switch(Map.member(owner, state.balances))
true =>
state.transfer(owner, someValue)
state.balances[owner]
_ => 0
BUT I can also use events in another record ? Not necessarily in this state.
I am afraid events are something completely different. They are a means to provide a list of this happened during the call messages. Events are emitted subsequently, one by one, and thus form a chronologically ordered list. You might think of them as a form of a log regarding the contract call. Once the call had been executed - you can read the list of events from the call object that had been produced. Or you can filter microblocks by certain events that happened in them. Events (will) provide a lot of different mechanisms to be exposed to users.
Although syntax around them is yet to be done, most probably events are going to be emitted by built-in functions (that you can further customize). After being emitted - they’d go in the call object for that call. Once emitted - contract will have no control over them anymore. From this perspective - it doesn’t make sense to have an event’s structure in your contract’s state (as events are handled for you by the virtual machine).
Stay tuned for events. Once they’re done, the protocol document will be updated accordingly.