Add ID contract examples to web ide without command defaults

This commit is contained in:
John David Pressman 2020-03-04 03:32:58 -08:00 committed by Pierre-Emmanuel Wulfman
parent 37a3fde6fd
commit e42e79eff3
7 changed files with 627 additions and 27 deletions

View File

@ -28,8 +28,8 @@ type action =
| Update_details(update_details)
| Skip(unit)
(* The prices kept in storage can be changed by bakers, though they should only be
adjusted down over time, not up. *)
/* The prices kept in storage can be changed by bakers, though they should only be
adjusted down over time, not up. */
type storage = {
identities: big_map (id, id_details),
next_id: int,
@ -37,7 +37,7 @@ type storage = {
skip_price: tez,
}
(** Preliminary thoughts on ids:
/** Preliminary thoughts on ids:
I very much like the simplicity of http://gurno.com/adam/mne/.
5 three letter words means you have a 15 character identity, not actually more
@ -50,7 +50,7 @@ something so people don't eat up the address space. 256 ^ 5 means you have a lot
of address space, but if people troll by skipping a lot that could be eaten up.
Should probably do some napkin calculations for how expensive skipping needs to
be to deter people from doing it just to chew up address space.
*)
*/
let buy = ((parameter, storage): (buy, storage)) : (list(operation), storage) => {
let void: unit =
@ -136,12 +136,12 @@ let update_details = ((parameter, storage): (update_details, storage)) :
let owner: address = current_id_details.owner;
let profile: bytes =
switch (new_profile) {
| None => (* Default *) current_id_details.profile
| None => /* Default */ current_id_details.profile
| Some(new_profile) => new_profile
};
let controller: address =
switch (new_controller) {
| None => (* Default *) current_id_details.controller
| None => /* Default */ current_id_details.controller
| Some new_controller => new_controller
};
let updated_id_details: id_details = {
@ -159,7 +159,7 @@ let update_details = ((parameter, storage): (update_details, storage)) :
});
};
(* Let someone skip the next identity so nobody has to take one that's undesirable *)
/* Let someone skip the next identity so nobody has to take one that's undesirable */
let skip = ((p,storage): (unit, storage)) => {
let void : unit =
if (amount != storage.skip_price) {

View File

@ -0,0 +1,195 @@
(*_*
name: ID Contract (CameLIGO)
language: cameligo
compile:
entrypoint: main
dryRun:
entrypoint: main
parameters: Increment 1
storage: 0
deploy:
entrypoint: main
storage: 0
evaluateValue:
entrypoint: ""
evaluateFunction:
entrypoint: add
parameters: 5, 6
*_*)
type id = int
type id_details = {
owner: address;
controller: address;
profile: bytes;
}
type buy = {
profile: bytes;
initial_controller: address option;
}
type update_owner = {
id: id;
new_owner: address;
}
type update_details = {
id: id;
new_profile: bytes option;
new_controller: address option;
}
type action =
| Buy of buy
| Update_owner of update_owner
| Update_details of update_details
| Skip of unit
(* The prices kept in storage can be changed by bakers, though they should only be
adjusted down over time, not up. *)
type storage = {
identities: (id, id_details) big_map;
next_id: int;
name_price: tez;
skip_price: tez;
}
(** Preliminary thoughts on ids:
I very much like the simplicity of http://gurno.com/adam/mne/.
5 three letter words means you have a 15 character identity, not actually more
annoying than an IP address and a lot more memorable than the raw digits. This
can be stored as a single integer which is then translated into the corresponding
series of 5 words.
I in general like the idea of having a 'skip' mechanism, but it does need to cost
something so people don't eat up the address space. 256 ^ 5 means you have a lot
of address space, but if people troll by skipping a lot that could be eaten up.
Should probably do some napkin calculations for how expensive skipping needs to
be to deter people from doing it just to chew up address space.
*)
let buy (parameter, storage: buy * storage) =
let void: unit =
if amount = storage.name_price
then ()
else (failwith "Incorrect amount paid.": unit)
in
let profile = parameter.profile in
let initial_controller = parameter.initial_controller in
let identities = storage.identities in
let new_id = storage.next_id in
let controller: address =
match initial_controller with
| Some addr -> addr
| None -> sender
in
let new_id_details: id_details = {
owner = sender ;
controller = controller ;
profile = profile ;
}
in
let updated_identities: (id, id_details) big_map =
Big_map.update new_id (Some new_id_details) identities
in
([]: operation list), {identities = updated_identities;
next_id = new_id + 1;
name_price = storage.name_price;
skip_price = storage.skip_price;
}
let update_owner (parameter, storage: update_owner * storage) =
if (amount <> 0mutez)
then (failwith "Updating owner doesn't cost anything.": (operation list) * storage)
else
let id = parameter.id in
let new_owner = parameter.new_owner in
let identities = storage.identities in
let current_id_details: id_details =
match Big_map.find_opt id identities with
| Some id_details -> id_details
| None -> (failwith "This ID does not exist.": id_details)
in
let is_allowed: bool =
if sender = current_id_details.owner
then true
else (failwith "You are not the owner of this ID.": bool)
in
let updated_id_details: id_details = {
owner = new_owner;
controller = current_id_details.controller;
profile = current_id_details.profile;
}
in
let updated_identities = Big_map.update id (Some updated_id_details) identities in
([]: operation list), {identities = updated_identities;
next_id = storage.next_id;
name_price = storage.name_price;
skip_price = storage.skip_price;
}
let update_details (parameter, storage: update_details * storage) =
if (amount <> 0mutez)
then (failwith "Updating details doesn't cost anything.": (operation list) * storage)
else
let id = parameter.id in
let new_profile = parameter.new_profile in
let new_controller = parameter.new_controller in
let identities = storage.identities in
let current_id_details: id_details =
match Big_map.find_opt id identities with
| Some id_details -> id_details
| None -> (failwith "This ID does not exist.": id_details)
in
let is_allowed: bool =
if (sender = current_id_details.controller) || (sender = current_id_details.owner)
then true
else (failwith ("You are not the owner or controller of this ID."): bool)
in
let owner: address = current_id_details.owner in
let profile: bytes =
match new_profile with
| None -> (* Default *) current_id_details.profile
| Some new_profile -> new_profile
in
let controller: address =
match new_controller with
| None -> (* Default *) current_id_details.controller
| Some new_controller -> new_controller
in
let updated_id_details: id_details = {
owner = owner;
controller = controller;
profile = profile;
}
in
let updated_identities: (id, id_details) big_map =
Big_map.update id (Some updated_id_details) identities in
([]: operation list), {identities = updated_identities;
next_id = storage.next_id;
name_price = storage.name_price;
skip_price = storage.skip_price;
}
(* Let someone skip the next identity so nobody has to take one that's undesirable *)
let skip (p,storage: unit * storage) =
let void: unit =
if amount = storage.skip_price
then ()
else (failwith "Incorrect amount paid.": unit)
in
([]: operation list), {identities = storage.identities;
next_id = storage.next_id + 1;
name_price = storage.name_price;
skip_price = storage.skip_price;
}
let main (action, storage: action * storage) : operation list * storage =
match action with
| Buy b -> buy (b, storage)
| Update_owner uo -> update_owner (uo, storage)
| Update_details ud -> update_details (ud, storage)
| Skip s -> skip ((), storage)

View File

@ -0,0 +1,197 @@
(*_*
name: ID Contract (PascaLIGO)
language: pascaligo
compile:
entrypoint: main
dryRun:
entrypoint: main
parameters: Increment 1
storage: 0
deploy:
entrypoint: main
storage: 0
evaluateValue:
entrypoint: ""
evaluateFunction:
entrypoint: add
parameters: 5, 6
*_*)
type id is int
type id_details is
record [
owner: address;
controller: address;
profile: bytes;
]
type buy is
record [
profile: bytes;
initial_controller: option(address);
]
type update_owner is
record [
id: id;
new_owner: address;
]
type update_details is
record [
id: id;
new_profile: option(bytes);
new_controller: option(address);
]
type action is
| Buy of buy
| Update_owner of update_owner
| Update_details of update_details
| Skip of unit
(* The prices kept in storage can be changed by bakers, though they should only be
adjusted down over time, not up. *)
type storage is
record [
identities: big_map (id, id_details);
next_id: int;
name_price: tez;
skip_price: tez;
]
(** Preliminary thoughts on ids:
I very much like the simplicity of http://gurno.com/adam/mne/.
5 three letter words means you have a 15 character identity, not actually more
annoying than an IP address and a lot more memorable than the raw digits. This
can be stored as a single integer which is then translated into the corresponding
series of 5 words.
I in general like the idea of having a 'skip' mechanism, but it does need to cost
something so people don't eat up the address space. 256 ^ 5 means you have a lot
of address space, but if people troll by skipping a lot that could be eaten up.
Should probably do some napkin calculations for how expensive skipping needs to
be to deter people from doing it just to chew up address space.
*)
function buy (const parameter : buy; const storage : storage) : list(operation) * storage is
begin
if amount = storage.name_price
then skip
else failwith("Incorrect amount paid.");
const profile : bytes = parameter.profile;
const initial_controller : option(address) = parameter.initial_controller;
var identities : big_map (id, id_details) := storage.identities;
const new_id : int = storage.next_id;
const controller : address =
case initial_controller of
Some(addr) -> addr
| None -> sender
end;
const new_id_details: id_details =
record [
owner = sender ;
controller = controller ;
profile = profile ;
];
identities[new_id] := new_id_details;
end with ((nil : list(operation)), record [
identities = identities;
next_id = new_id + 1;
name_price = storage.name_price;
skip_price = storage.skip_price;
])
function update_owner (const parameter : update_owner; const storage : storage) :
list(operation) * storage is
begin
if (amount =/= 0mutez)
then
begin
failwith("Updating owner doesn't cost anything.");
end
else skip;
const id : int = parameter.id;
const new_owner : address = parameter.new_owner;
var identities : big_map (id, id_details) := storage.identities;
const id_details : id_details =
case identities[id] of
Some(id_details) -> id_details
| None -> (failwith("This ID does not exist."): id_details)
end;
var is_allowed : bool := False;
if sender = id_details.owner
then is_allowed := True
else failwith("You are not the owner of this ID.");
id_details.owner := new_owner;
identities[id] := id_details;
end with ((nil: list(operation)), record [
identities = identities;
next_id = storage.next_id;
name_price = storage.name_price;
skip_price = storage.skip_price;
])
function update_details (const parameter : update_details; const storage : storage ) :
list(operation) * storage is
begin
if (amount =/= 0mutez)
then failwith("Updating details doesn't cost anything.")
else skip;
const id : int = parameter.id;
const new_profile : option(bytes) = parameter.new_profile;
const new_controller : option(address) = parameter.new_controller;
const identities : big_map (id, id_details) = storage.identities;
const id_details: id_details =
case identities[id] of
Some(id_details) -> id_details
| None -> (failwith("This ID does not exist."): id_details)
end;
var is_allowed : bool := False;
if (sender = id_details.controller) or (sender = id_details.owner)
then is_allowed := True
else failwith("You are not the owner or controller of this ID.");
const owner: address = id_details.owner;
const profile: bytes =
case new_profile of
None -> (* Default *) id_details.profile
| Some(new_profile) -> new_profile
end;
const controller: address =
case new_controller of
None -> (* Default *) id_details.controller
| Some(new_controller) -> new_controller
end;
id_details.owner := owner;
id_details.controller := controller;
id_details.profile := profile;
identities[id] := id_details;
end with ((nil: list(operation)), record [
identities = identities;
next_id = storage.next_id;
name_price = storage.name_price;
skip_price = storage.skip_price;
])
(* Let someone skip the next identity so nobody has to take one that's undesirable *)
function skip_ (const p: unit; const storage: storage) : list(operation) * storage is
begin
if amount = storage.skip_price
then skip
else failwith("Incorrect amount paid.");
end with ((nil: list(operation)), record [
identities = storage.identities;
next_id = storage.next_id + 1;
name_price = storage.name_price;
skip_price = storage.skip_price;
])
function main (const action : action; const storage : storage) : list(operation) * storage is
case action of
| Buy(b) -> buy (b, storage)
| Update_owner(uo) -> update_owner (uo, storage)
| Update_details(ud) -> update_details (ud, storage)
| Skip(s) -> skip_ (unit, storage)
end;

View File

@ -0,0 +1,203 @@
(*_*
name: ID Contract (ReasonLIGO)
language: reasonligo
compile:
entrypoint: main
dryRun:
entrypoint: main
parameters: Increment 1
storage: 0
deploy:
entrypoint: main
storage: 0
evaluateValue:
entrypoint: ""
evaluateFunction:
entrypoint: add
parameters: 5, 6
*_*)
type id = int
type id_details = {
owner: address,
controller: address,
profile: bytes,
}
type buy = {
profile: bytes,
initial_controller: option(address),
}
type update_owner = {
id: id,
new_owner: address,
}
type update_details = {
id: id,
new_profile: option(bytes),
new_controller: option(address),
}
type action =
| Buy(buy)
| Update_owner(update_owner)
| Update_details(update_details)
| Skip(unit)
(* The prices kept in storage can be changed by bakers, though they should only be
adjusted down over time, not up. *)
type storage = {
identities: big_map (id, id_details),
next_id: int,
name_price: tez,
skip_price: tez,
}
(** Preliminary thoughts on ids:
I very much like the simplicity of http://gurno.com/adam/mne/.
5 three letter words means you have a 15 character identity, not actually more
annoying than an IP address and a lot more memorable than the raw digits. This
can be stored as a single integer which is then translated into the corresponding
series of 5 words.
I in general like the idea of having a 'skip' mechanism, but it does need to cost
something so people don't eat up the address space. 256 ^ 5 means you have a lot
of address space, but if people troll by skipping a lot that could be eaten up.
Should probably do some napkin calculations for how expensive skipping needs to
be to deter people from doing it just to chew up address space.
*)
let buy = ((parameter, storage): (buy, storage)) : (list(operation), storage) => {
let void: unit =
if (amount == storage.name_price) { (); }
else { failwith("Incorrect amount paid."); };
let profile = parameter.profile;
let initial_controller = parameter.initial_controller;
let identities = storage.identities;
let new_id = storage.next_id;
let controller: address =
switch (initial_controller) {
| Some(addr) => addr
| None => sender
};
let new_id_details: id_details = {
owner : sender,
controller : controller,
profile : profile,
};
let updated_identities: big_map (id, id_details) =
Big_map.update(new_id, Some(new_id_details), identities);
(([]: list(operation)), {
identities : updated_identities,
next_id : new_id + 1,
name_price : storage.name_price,
skip_price : storage.skip_price,
});
};
let update_owner = ((parameter, storage): (update_owner, storage)) : (list(operation), storage) => {
let void: unit =
if (amount != 0mutez) {
failwith("Updating owner doesn't cost anything.");
}
else { (); };
let id : int = parameter.id;
let new_owner = parameter.new_owner;
let identities = storage.identities;
let current_id_details: id_details =
switch (Big_map.find_opt(id, identities)) {
| Some(id_details) => id_details
| None => (failwith("This ID does not exist."): id_details)
};
let is_allowed: bool =
if (sender == current_id_details.owner) { true; }
else { (failwith("You are not the owner of this ID."): bool); };
let updated_id_details: id_details = {
owner : new_owner,
controller : current_id_details.controller,
profile : current_id_details.profile,
};
let updated_identities = Big_map.update(id, (Some updated_id_details), identities);
(([]: list(operation)), {
identities : updated_identities,
next_id : storage.next_id,
name_price : storage.name_price,
skip_price : storage.skip_price,
});
};
let update_details = ((parameter, storage): (update_details, storage)) :
(list(operation), storage) => {
let void : unit =
if (amount != 0mutez) {
failwith("Updating details doesn't cost anything.");
}
else { (); };
let id = parameter.id;
let new_profile = parameter.new_profile;
let new_controller = parameter.new_controller;
let identities = storage.identities;
let current_id_details: id_details =
switch (Big_map.find_opt(id, identities)) {
| Some(id_details) => id_details
| None => (failwith("This ID does not exist."): id_details)
};
let is_allowed: bool =
if ((sender != current_id_details.controller) &&
(sender != current_id_details.owner)) {
(failwith ("You are not the owner or controller of this ID."): bool)
}
else { true; };
let owner: address = current_id_details.owner;
let profile: bytes =
switch (new_profile) {
| None => (* Default *) current_id_details.profile
| Some(new_profile) => new_profile
};
let controller: address =
switch (new_controller) {
| None => (* Default *) current_id_details.controller
| Some new_controller => new_controller
};
let updated_id_details: id_details = {
owner : owner,
controller : controller,
profile : profile,
};
let updated_identities: big_map (id, id_details) =
Big_map.update(id, (Some updated_id_details), identities);
(([]: list(operation)), {
identities : updated_identities,
next_id : storage.next_id,
name_price : storage.name_price,
skip_price : storage.skip_price,
});
};
(* Let someone skip the next identity so nobody has to take one that's undesirable *)
let skip = ((p,storage): (unit, storage)) => {
let void : unit =
if (amount != storage.skip_price) {
failwith("Incorrect amount paid.");
}
else { (); };
(([]: list(operation)), {
identities : storage.identities,
next_id : storage.next_id + 1,
name_price : storage.name_price,
skip_price : storage.skip_price,
});
};
let main = ((action, storage): (action, storage)) : (list(operation), storage) => {
switch (action) {
| Buy(b) => buy((b, storage))
| Update_owner(uo) => update_owner((uo, storage))
| Update_details ud => update_details((ud, storage))
| Skip s => skip(((), storage))
};
};

View File

@ -1,11 +1,10 @@
open Trace
open Test_helpers
open Ast_simplified
open Ast_imperative
let mtype_file f =
let%bind simplified = Ligo.Compile.Of_source.compile f (Syntax_name "pascaligo") in
let%bind typed,state = Ligo.Compile.Of_simplified.compile simplified in
let type_file f =
let%bind typed,state = Ligo.Compile.Utils.type_file f "pascaligo" Env in
ok (typed,state)
let get_program =
@ -13,14 +12,13 @@ let get_program =
fun () -> match !s with
| Some s -> ok s
| None -> (
let%bind program = mtype_file "./contracts/id.ligo" in
let%bind program = type_file "./contracts/id.ligo" in
s := Some program ;
ok program
)
let compile_main () =
let%bind simplified = Ligo.Compile.Of_source.compile "./contracts/id.ligo" (Syntax_name "pascaligo") in
let%bind typed_prg,_ = Ligo.Compile.Of_simplified.compile simplified in
let%bind typed_prg,_ = get_program () in
let%bind mini_c_prg = Ligo.Compile.Of_typed.compile typed_prg in
let%bind michelson_prg = Ligo.Compile.Of_mini_c.aggregate_and_compile_contract mini_c_prg "main" in
let%bind (_contract: Tezos_utils.Michelson.michelson) =
@ -96,7 +94,7 @@ let buy_id_sender_addr () =
("profile", new_website)]
in
let param = e_record_ez [("profile", owner_website) ;
("initial_controller", (e_typed_none t_address))] in
("initial_controller", (e_typed_none (t_address ())))] in
let new_storage = e_record_ez [("identities", (e_big_map
[(e_int 0, id_details_1) ;
(e_int 1, id_details_2)])) ;
@ -324,8 +322,8 @@ let update_details_unchanged () =
("skip_price", e_mutez 1000000) ; ]
in
let param = e_record_ez [("id", e_int 1) ;
("new_profile", e_typed_none t_bytes) ;
("new_controller", e_typed_none t_address)] in
("new_profile", e_typed_none (t_bytes ())) ;
("new_controller", e_typed_none (t_address ()))] in
let%bind () = expect_eq ~options program "update_details"
(e_pair param storage)
(e_pair (e_list []) storage)

View File

@ -1,11 +1,10 @@
open Trace
open Test_helpers
open Ast_simplified
open Ast_imperative
let mtype_file f =
let%bind simplified = Ligo.Compile.Of_source.compile f (Syntax_name "reasonligo") in
let%bind typed,state = Ligo.Compile.Of_simplified.compile simplified in
let retype_file f =
let%bind typed,state = Ligo.Compile.Utils.type_file f "reasonligo" Env in
ok (typed,state)
let get_program =
@ -13,14 +12,13 @@ let get_program =
fun () -> match !s with
| Some s -> ok s
| None -> (
let%bind program = mtype_file "./contracts/id.religo" in
let%bind program = retype_file "./contracts/id.religo" in
s := Some program ;
ok program
)
let compile_main () =
let%bind simplified = Ligo.Compile.Of_source.compile "./contracts/id.religo" (Syntax_name "reasonligo") in
let%bind typed_prg,_ = Ligo.Compile.Of_simplified.compile simplified in
let%bind typed_prg,_ = get_program () in
let%bind mini_c_prg = Ligo.Compile.Of_typed.compile typed_prg in
let%bind michelson_prg = Ligo.Compile.Of_mini_c.aggregate_and_compile_contract mini_c_prg "main" in
let%bind (_contract: Tezos_utils.Michelson.michelson) =
@ -96,7 +94,7 @@ let buy_id_sender_addr () =
("profile", new_website)]
in
let param = e_record_ez [("profile", owner_website) ;
("initial_controller", (e_typed_none t_address))] in
("initial_controller", (e_typed_none (t_address ())))] in
let new_storage = e_record_ez [("identities", (e_big_map
[(e_int 0, id_details_1) ;
(e_int 1, id_details_2)])) ;
@ -324,8 +322,8 @@ let update_details_unchanged () =
("skip_price", e_mutez 1000000) ; ]
in
let param = e_record_ez [("id", e_int 1) ;
("new_profile", e_typed_none t_bytes) ;
("new_controller", e_typed_none t_address)] in
("new_profile", e_typed_none (t_bytes ())) ;
("new_controller", e_typed_none (t_address ()))] in
let%bind () = expect_eq ~options program "update_details"
(e_pair param storage)
(e_pair (e_list []) storage)

View File

@ -109,6 +109,15 @@ async function main() {
// const EXAMPLES_GLOB = '**/*.ligo';
// const files = await findFiles(EXAMPLES_GLOB, EXAMPLES_DIR);
const CURATED_EXAMPLES = [
'pascaligo/arithmetic-contract.ligo',
'cameligo/arithmetic-contract.ligo',
'reasonligo/arithmetic-contract.ligo',
'pascaligo/id.ligo',
'cameligo/id.mligo',
'reasonligo/id.religo',
];
const EXAMPLES_DEST_DIR = join(process.cwd(), 'build', 'static', 'examples');
fs.mkdirSync(EXAMPLES_DEST_DIR, { recursive: true });