diff --git a/src/fd_gridsd.erl b/src/fd_gridsd.erl index 6b53b00..c969629 100644 --- a/src/fd_gridsd.erl +++ b/src/fd_gridsd.erl @@ -21,8 +21,6 @@ -include("$zx_include/zx_logger.hrl"). --type mh_str() :: string(). - %% for craig's autism -record(sp, {recipient :: string(), @@ -30,13 +28,11 @@ payload :: binary()}). -type search_pattern() :: #sp{}. +-type sp() :: search_pattern(). -record(s, - {current_gen_height :: pos_integer(), - current_gen_hash :: string(), - current_gen_seen_mb_hashes :: [mh_str()], - past_gen_seen_mb_hashes :: [mh_str()], - looking_for :: [search_pattern()]}). + {looking_for = [] :: [{sp(), NotifyWhenSeen :: pid()}]}). + -type state() :: #s{}. @@ -44,11 +40,15 @@ %% caller context %%----------------------------------------------------------------------------- --spec get_url(Amount, Payload) -> {ok, URL, QR_PNG} | {error, term()} - when Amount :: none | pos_integer(), - Payload :: none | binary(), +-spec get_url(Amount, Payload) -> Result + when Amount :: non_neg_integer(), + Payload :: binary(), + Result :: {ok, URL, QR_PNG} + | {error, term()}, URL :: string(), QR_PNG :: binary(). +% @doc +% Very important: amount MUST be an integer >= 0 get_url(Amount, Payload) -> gen_server:call(?MODULE, {get_url, Amount, Payload}). @@ -105,18 +105,66 @@ terminate(_, _) -> %%----------------------------------------------------------------------------- -spec i_get_url(Amount, Payload, From, State) -> Result - when Amount :: none | pos_integer(), - Payload :: none | binary(), - From :: {pid(), reference()}, - State :: state(), - URL :: string(), - QR_PNG :: binary(). - Result :: {ok, URL, QR_PNG, NewState} - | {error, term()}. + when Amount :: non_neg_integer(), + Payload :: binary(), + From :: {pid(), reference()}, + State :: state(), + Result :: {ok, URL, QR_PNG, NewState} + | {error, term()}, + URL :: string(), + QR_PNG :: binary(), + NewState :: state(). -i_get_url(Amount, Payload, From, State) -> +i_get_url(Amount, Payload, {FromPID, _}, State) + when is_integer(Amount), Amount >= 0, + is_binary(Payload) -> NetworkId = fewd:network_id(), - Pubkey = fewd:pubkey(), - URL = gmgrids:encode({spend, NetworkId, Pubkey}, - [{amount, Amount}, {payload, Payload}]), - + Recipient = fewd:akstr(), + URL = gmgrids:encode({spend, NetworkId, Recipient}, + [{amount, Amount}, + {payload, Payload}]), + URLBin = unicode:characters_to_binary(URL), + PNG = qr:encode_png(URLBin), + case i_register(Recipient, Amount, Payload, FromPID, State) of + {ok, NewState} -> {ok, URL, PNG, NewState}; + Error -> Error + end; +i_get_url(Amount, _, _, _) when (not is_integer(Amount)) -> + {error, non_integer_amount}; +i_get_url(Amount, _, _, _) when Amount < 0 -> + {error, negative_amount}; +i_get_url(_, _, _, _) -> + {error, bad_payload}. + + +i_register(Recipient, Amount, Payload, FromPID, State = #s{looking_for = Patterns}) -> + SP = i_sp(Recipient, Amount, Payload), + case i_lookup(SP, State) of + not_found -> + NewPattern = {SP, FromPID}, + NewPatterns = [NewPattern | Patterns], + NewState = State#s{looking_for = NewPatterns}, + {ok, NewState}; + {found, _} -> + {error, already_registered} + end. + +%% future proofing +i_sp(Recipient, Amount, Payload) -> + {sp, Recipient, Amount, Payload}. + + +-spec i_lookup(SearchPattern, State) -> Result + when SearchPattern :: sp(), + State :: state(), + Result :: {found, NotifyPID :: pid()} + | not_found. + +% @private look up search pattern and see if we're looking for it + +i_lookup(SearchPattern, State) -> + #s{looking_for = Patterns} = State, + case lists:keyfind(SearchPattern, 1, Patterns) of + false -> not_found; + {_, Notify} -> {found, Notify} + end. diff --git a/src/fewd.erl b/src/fewd.erl index cc74f93..21b86a7 100644 --- a/src/fewd.erl +++ b/src/fewd.erl @@ -9,7 +9,7 @@ -copyright("Peter Harpending "). -license("BSD-2-Clause-FreeBSD"). --export([network_id/0, pubkey/0]). +-export([network_id/0, pubkey/0, akstr/0]). -export([listen/1, ignore/0]). -export([start/2, stop/1]). @@ -18,6 +18,7 @@ network_id() -> "groot.testnet". pubkey() -> pad32("fewd demo"). +akstr() -> gmgrids:akstr(pubkey()). pad32(Bytes) ->