This commit is contained in:
Peter Harpending 2026-04-20 14:32:59 -07:00
parent f71826357b
commit ac19eff060
12 changed files with 224 additions and 7 deletions

1
.gitignore vendored
View File

@ -18,3 +18,4 @@ logs
*.iml *.iml
rebar3.crashdump rebar3.crashdump
*~ *~
/gaj

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "lib/gajumaru"]
path = lib/gajumaru
url = https://git.qpq.swiss/QPQ-AG/gajumaru.git

42
Makefile Normal file
View File

@ -0,0 +1,42 @@
APP_NAME = gmplugin_hello
GAJUMARU_LIB = lib/gajumaru
BUILD_DIR = $(GAJUMARU_LIB)/_build/prod/rel/gajumaru
TARGET_NETWORK = localnet
# steps are
# 1. call rebar3 gm_plugin to build the plugin
# 2. build the node
# 3. start the node with a configuration where it knows it needs to load our plugin
# 4. run a shell in the node context
all: compile
init: submodules
submodules:
git submodule init
git submodule update
compile:
rebar3 compile
build-my-plugin: compile
rebar3 gm_plugin
# adapted from gmp_ix
build-gm-with-my-plugin: build-my-plugin
cp _build/default/$(APP_NAME).ez $(GAJUMARU_LIB)/plugins
cd $(GAJUMARU_LIB) && make prod-build
cp -rvf gmconfig/$(TARGET_NETWORK)/gajumaru/* $(BUILD_DIR)
fresh-console: build-gm-with-my-plugin console
console:
$(BUILD_DIR)/bin/gajumaru console
clean:
rebar3 clean
cd $(GAJUMARU_LIB) && make prod-clean
rm -f $(GAJUMARU_LIB)/plugins/$(APP_NAME).ez

View File

@ -1,9 +1,64 @@
gmplugin_hello # `gmplugin_hello`
=====
An OTP application This is a minimal Gajumaru plugin. This is meant to be a minimal working
template on which development can occur immediately.
Build # Quickstart
-----
$ rebar3 compile ## System Prereqs
## After clone
```
make init
make build-gm-with-my-plugin
```
## Running
```
make fresh-console
```
```
(gajumaru@localhost)1> gmplugin_hello_app:hello().
"hello, world"
(gajumaru@localhost)2> gmplugin_hello_app:network_id().
<<"localnet">>
(gajumaru@localhost)3> gmplugin_hello_app:height().
{ok,1}
```
# Questions
## What is a Gajumaru?
In the context of this document, "Gajumaru" with no qualification means the
Erlang software that runs a gajumaru node.
## What is a Gajumaru plugin?
A Gajumaru plugin is an Erlang application that runs in the same Erlang process
context as `gajumaru`, meaning it can natively call `aeu_db:whatever`.
## What is the point of a Gajumaru plugin?
Let's say you're developing a point-of-sale app for your daughter's lemonade
stand. Your application needs to interact with Gajumaru in some way. You're
going to have your LemonPay app talk to your own local gajumaru node that
you're running on your old laptop on `192.168.2.1`.
The idea here is that the portion of your LemonPay business logic that needs to
interact intimately with data on the chain should run in the relatively
frictionless Erlang-to-Erlang context of the gajumaru application. Then you
expose a service interface on port `9876` that is tailored specifically for
LemonPay. LemonPay talks to `192.168.2.1:9876`.
## How does anything do anything?
The important thing to understand is that **gajumaru starts your plugin**.
Therefore, when you're developing and iterating on your plugin, you need to
have a way to start gajumaru, start your plugin, mess around with it.

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,51 @@
{
"logging": {
"levels": [
{
"target": "console",
"level": "debug"
}
]
},
"chain" : {
"db_backend" : "rocksdb",
"persist" : true
},
"governance" : {
"network_id" : "localnet"
},
"system" : {
"dev_mode" : true,
"plugins" : [
{
"name" : "gmplugin_hello"
}
]
},
"hard_forks" : {
"versions" : {
"1" : {
"height" : 0,
"type" : {
"on_demand" : {
"mining" : {
"autostart" : false
}
}
},
"data" : {
"data" : [
{ "accounts" : {
"ak_4JJZNZynTy7RhTQBn7k9q6ZRehwLFPB1ncSQcyenZ3j3zYn6c" : 1000000000000000000000,
"ak_2PPgx59oeXLKL87jNkxE5wFY5hC3vNS5kXWFQbCoy3znMcDHo" : 1000000000000000000000,
"ak_2nyQQiU38XGDYdfU4Z9RXmyY5YBcPxbpnGGvvBs8i6CCgiJjAM" : 1000000000000000000000,
"ak_3AVVjGNmSQCT6bzUWjhhZYd3yaFWztzyVANx4QD9sFBRxAsGM" : 1000000000000000000000,
"ak_2GZCX7k6AorKpF59XYQVmNehBXM4BD1XWaP9WjeHFgcCzeUvRM" : 1000000000000000000000
}
}
]
}
}
}
}
}

View File

View File

1
lib/gajumaru Submodule

@ -0,0 +1 @@
Subproject commit 752c8d0ae5546ce42e3ec1bd4326606459975e20

View File

@ -1,5 +1,18 @@
{erl_opts, [debug_info]}. {erl_opts, [debug_info]}.
{deps, []}.
% there's some bug somewhere... this list must be nonempty for some reason
{deps, [
{gmserialization, {gm, gmserialization}}
]}.
{project_apps_dir, "lib/gajumaru/apps"}.
{plugins, [
{gmplugin_rebar3, {git, "https://git.qpq.swiss/QPQ-AG/gmplugin_rebar3.git", {branch,"master"}}}
]}.
{gajumaru_root, {git, "https://git.qpq.swiss/QPQ-AG/gajumaru", "master"}}.
{shell, [ {shell, [
%% {config, "config/sys.config"}, %% {config, "config/sys.config"},

17
rebar.lock Normal file
View File

@ -0,0 +1,17 @@
{"1.2.0",
[{<<"base58">>,
{git,"https://git.qpq.swiss/QPQ-AG/erl-base58.git",
{ref,"e6aa62eeae3d4388311401f06e4b939bf4e94b9c"}},
1},
{<<"eblake2">>,{pkg,<<"eblake2">>,<<"1.0.0">>},1},
{<<"enacl">>,
{git,"https://git.qpq.swiss/QPQ-AG/enacl.git",
{ref,"4eb7ec70084ba7c87b1af8797c4c4e90c84f95a2"}},
1},
{<<"gmserialization">>,{gm,gmserialization},0}]}.
[
{pkg_hash,[
{<<"eblake2">>, <<"EC8AD20E438AAB3F2E8D5D118C366A0754219195F8A0F536587440F8F9BCF2EF">>}]},
{pkg_hash_ext,[
{<<"eblake2">>, <<"3C4D300A91845B25D501929A26AC2E6F7157480846FAB2347A4C11AE52E08A99">>}]}
].

View File

@ -7,8 +7,16 @@
-behaviour(application). -behaviour(application).
-export([start/2, stop/1]). -export([start/2, stop/1]).
% tests
-export([
hello/0,
network_id/0,
height/0
]).
start(_StartType, _StartArgs) -> start(_StartType, _StartArgs) ->
gmplugin_hello_sup:start_link(). gmplugin_hello_sup:start_link().
@ -16,3 +24,28 @@ stop(_State) ->
ok. ok.
%% internal functions %% internal functions
%%
-spec hello() -> string().
hello() ->
"hello, world".
-spec network_id() -> binary().
network_id() ->
aec_governance:get_network_id().
-spec height() -> {ok, Height :: pos_integer()}
| {error, no_top_block}.
height() ->
case aec_chain:top_height() of
undefined -> {error, no_top_block};
Height -> {ok, Height}
end.