Compare commits

...

2 Commits

Author SHA1 Message Date
Peter Harpending
5ac88efa0c update readme 2026-01-12 18:41:53 -08:00
Peter Harpending
7299dbc9f1 deploy hello world contract to testnet 2025-09-26 14:06:54 -07:00
5 changed files with 199 additions and 1157 deletions

1166
README.md

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,4 @@
priv/keypair.eterms
.eunit
deps
*.o

View File

@ -0,0 +1,16 @@
/**
* Hello world contract in sophia
*
* Copyright (C) 2025, QPQ AG
*/
@compiler == 9.0.0
contract Hello =
type state = unit
entrypoint init(): state =
()
entrypoint hello(): string =
"hello"

View File

@ -8,7 +8,6 @@
-author("Peter Harpending <peterharpending@qpq.swiss>").
-copyright("Peter Harpending <peterharpending@qpq.swiss>").
%% for our edification
-export([listen/1, ignore/0]).
-export([start/0]).
@ -17,6 +16,12 @@
-export([start/2, stop/1]).
-include("$zx_include/zx_logger.hrl").
%------------------------------------------------------
% API
%------------------------------------------------------
-spec listen(PortNum) -> Result
when PortNum :: inet:port_num(),
@ -77,7 +82,7 @@ start(normal, _Args) ->
hz() ->
ok = application:ensure_started(hakuzaru),
ok = hz:chain_nodes([testnet_node()]),
ok = zx:tell("hz status: ~tp", [hz:status()]),
ok = tell("hz status: ~tp", [hz:status()]),
ok.
testnet_ip() ->

164
gex_httpd/src/gh_ct.erl Normal file
View File

@ -0,0 +1,164 @@
% @doc miscellaneous contract functions
%
% mostly wrappers for ec_utils and hakuzaru
-module(gh_ct).
-export_type([
keypair/0
]).
-export([
deploy/2,
get_pubkey_akstr/0, get_keypair/0,
keypair_file/0,
read_keypair_from_file/1, write_keypair_to_file/2, fmt_keypair/1,
fmt_pubkey_api/1,
gen_keypair/0
]).
-include("$zx_include/zx_logger.hrl").
%------------------------------------------------------
% API: types
%------------------------------------------------------
-type keypair() :: #{public := binary(),
secret := binary()}.
%------------------------------------------------------
% API: functions
%------------------------------------------------------
-spec deploy(ContractSrcPath, InitArgs) -> Result
when ContractSrcPath :: string(),
InitArgs :: term(),
Result :: {ok, term()}
| {error, term()}. %% FIXME
deploy(ContractSrcPath, InitArgs) ->
CreatorId = get_pubkey_akstr(),
case hz:contract_create(CreatorId, ContractSrcPath, InitArgs) of
{ok, ContractCreateTx} ->
push(ContractCreateTx);
Error ->
tell(error, "gh_ct:deploy(~tp, ~tp) error: ~tp", [ContractSrcPath, InitArgs, Error]),
Error
end.
push(ContractCreateTx) ->
#{secret := SecretKey} = get_keypair(),
SignedTx = hz:sign_tx(ContractCreateTx, SecretKey),
tell(info, "pushing signed tx: ~tp", [SignedTx]),
hz:post_tx(SignedTx).
-spec get_pubkey_akstr() -> string().
% @doc
% get our pubkey as an ak_... string
get_pubkey_akstr() ->
#{public := PK} = get_keypair(),
unicode:characters_to_list(fmt_pubkey_api(PK)).
-spec get_keypair() -> keypair().
% @doc
% if can read keypair from `keypair_file()`, do so
% otherwise generate one
%
% prints warnings if IO ops fail
get_keypair() ->
case read_keypair_from_file(keypair_file()) of
{ok, KP} ->
KP;
% probably file
ReadError ->
tell(warning, "gh_ct:get_keypair(): read error: ~tp", [ReadError]),
KP = gen_keypair(),
% try writing to file
%tell(info, "gh_ct:get_keypair(): attempting to write keypair to file...", []),
%case write_keypair_to_file(keypair_file(), KP) of
% ok -> tell(info, "gh_ct:get_keypair(): write successful!", []);
% Error -> tell(warning, "gh_ct:get_keypair(): write error: ~tp", [Error])
%end,
KP
end.
-spec keypair_file() -> string().
% @doc
% normal file where operating keypair is stored
keypair_file() ->
filename:join([zx:get_home(), "priv", "keypair.eterms"]).
-spec read_keypair_from_file(FilePath) -> Result
when FilePath :: string(),
Result :: {ok, keypair()}
| {error, Reason :: term()}.
% @doc
% try to read keypair from file in `file:consult/1` format.
read_keypair_from_file(FilePath) ->
case file:consult(FilePath) of
{ok, [{public, PK}, {secret, SK}]} ->
{ok, #{public => PK, secret => SK}};
{ok, [{secret, SK}, {public, PK}]} ->
{ok, #{public => PK, secret => SK}};
{ok, Bad} ->
tell(warning, "read malformed keypair from file ~tp: ~tp", [FilePath, Bad]),
{error, bad_keypair};
Error ->
Error
end.
-spec write_keypair_to_file(FilePath, Keypair) -> Result
when FilePath :: string(),
Keypair :: keypair(),
Result :: ok
| {error, Reason :: term()}.
% @doc
% Write keypair to file as
%
% ```
% {public, <<...>>}.
% {secret, <<..>>}.
% ```
write_keypair_to_file(FP, KP) ->
file:write_file(FP, fmt_keypair(KP)).
-spec fmt_pubkey_api(binary()) -> binary().
fmt_pubkey_api(Bin) ->
gmser_api_encoder:encode(account_pubkey, Bin).
-spec fmt_keypair(keypair()) -> iolist().
% @doc
% format keypair in `file:consult/1` format
fmt_keypair(#{public := PK, secret := SK}) ->
io_lib:format("{public, ~tp}.~n"
"{secret, ~tp}.~n",
[PK, SK]).
-spec gen_keypair() -> keypair().
% @doc
% Generate a keypair
gen_keypair() ->
ecu_eddsa:sign_keypair().