github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/HOWTO.md (about)

     1  # How to run a w3bstream node with docker
     2  
     3  Suppose `$working_dir` is the directory you want to store your data.
     4  
     5  ## Install docker-compose
     6  
     7  https://docker-docs.netlify.app/compose/install/
     8  
     9  ## Download docker-compose.yaml
    10  
    11  ```bash
    12  cd $working_dir
    13  curl https://raw.githubusercontent.com/machinefi/w3bstream/main/docker-compose.yaml > docker-compose.yaml
    14  docker-compose up -d
    15  ```
    16  
    17  You are all set.
    18  
    19  ## Customize settings
    20  
    21  ```bash
    22  cd $working_dir
    23  curl https://raw.githubusercontent.com/machinefi/w3bstream/main/.env.tmpl > .env
    24  ```
    25  
    26  then modify the corresponding parameters in `.env`, and restart your docker
    27  containers
    28  
    29  ```bash
    30  docker-compose restart
    31  ```
    32  
    33  # Run W3bstream node from code
    34  
    35  If you are interested in diving into the code and run the node using a locally built docker, here is the steps of
    36  building the docker image from code.
    37  
    38  ### Build docker image from code
    39  
    40  ```bash
    41  make build_backend_image
    42  ```
    43  
    44  ### Run server in docker containers
    45  
    46  ```bash
    47   make run_docker
    48   ```
    49  
    50  ### Stop server running in docker containers
    51  
    52   ```bash
    53   make stop_docker
    54   ```
    55  
    56  ### Delete docker resources
    57  
    58   ```bash
    59   make drop_docker
    60   ```
    61  
    62  # How to interact with W3bstream Node Using CLI
    63  
    64  ### Login (fetch auth token)
    65  
    66  command
    67  
    68  ```sh
    69  # the default password is "iotex.W3B.admin"
    70  echo '{"username":"admin","password":"iotex.W3B.admin"}' | http put :8888/srv-applet-mgr/v0/login 
    71  ```
    72  
    73  output like
    74  
    75  ```json
    76  {
    77    "accountID": "${account_id}",
    78    "expireAt": "2022-09-23T07:20:08.099601+08:00",
    79    "issuer": "srv-applet-mgr",
    80    "token": "${token}"
    81  }
    82  ```
    83  
    84  ```sh
    85  export TOK=${token}
    86  ```
    87  
    88  ### Login/Signup with wallet address
    89  
    90  ```shell
    91  export MESSAGE=...   # siwe serailized message
    92  export SIGNATURE=... # message signature
    93  echo '{"message":"'$MESSAGE'","signature":"'$SIGNATURE'"}' | http put :8888/srv-applet-mgr/v0/login/eth
    94  ```
    95  
    96  output like:
    97  
    98  ```json
    99  {
   100    "accountID": "186912900253363206",
   101    "accountRole": "DEVELOPER",
   102    "expireAt": "2023-03-16T19:07:57.624481+08:00",
   103    "issuer": "iotex-w3bstream",
   104    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJQYXlsb2FkIjoiMTg2OTEyOTAwMjUzMzYzMjA2IiwiaXNzIjoiaW90ZXgtdzNic3RyZWFtIiwiZXhwIjoxNjc4OTY0ODc3fQ.u7wLOBUeehHTURNY2L2d_F4u-dZ5sHnBBHZKujnpMRw"
   105  }
   106  ```
   107  
   108  ### Get Account's Operator Address
   109  
   110  ```shell
   111  http get :8888/srv-applet-mgr/v0/account/operatoraddr -A bearer -a $TOK
   112  
   113  ```
   114  
   115  ### Create your project with default config
   116  
   117  command
   118  
   119  ```sh
   120  export PROJECTNAME=${project_name}
   121  echo '{"name":"'$PROJECTNAME'"}' | http post :8888/srv-applet-mgr/v0/project -A bearer -a $TOK
   122  ```
   123  
   124  output like
   125  
   126  ```json
   127  {
   128    "accountID": "11276794515805192",
   129    "channelState": true,
   130    "createdAt": "2023-05-03T05:39:17.835566714Z",
   131    "database": {
   132      "schemas": [
   133        {
   134          "schema": "public"
   135        }
   136      ]
   137    },
   138    "envs": {
   139      "env": null
   140    },
   141    "name": "demo",
   142    "projectID": "11276839333473280",
   143    "updatedAt": "2023-05-03T05:39:17.835567047Z"
   144  }
   145  ```
   146  
   147  ### Create project with database and env vars configuration
   148  
   149  ```sh
   150  export PROJECTDATABASE='{
   151    "schemas": [
   152      {
   153        "schema": "public",
   154        "tables": [
   155          {
   156            "name": "t_demo",
   157            "desc": "demo table",
   158            "cols": [
   159              {
   160                "name": "f_id",
   161                "constrains": {
   162                  "datatype": "INT64",
   163                  "autoincrement": true,
   164                  "desc": "primary id"
   165                }
   166              },
   167              {
   168                "name": "f_name",
   169                "constrains": {
   170                  "datatype": "TEXT",
   171                  "length": 255,
   172                  "desc": "name"
   173                }
   174              },
   175              {
   176                "name": "f_amount",
   177                "constrains": {
   178                  "datatype": "FLOAT64",
   179                  "desc": "amount"
   180                }
   181              },
   182              {
   183                "name": "f_income",
   184                "constrains": {
   185                  "datatype": "DECIMAL",
   186                  "length": 512,
   187                  "decimal": 512,
   188                  "default": "0",
   189                  "desc": "income"
   190                }
   191              },
   192              {
   193                "name": "f_comment",
   194                "constrains": {
   195                  "datatype": "TEXT",
   196                  "default": "''",
   197                  "null": true,
   198                  "desc": "comment"
   199                }
   200              }
   201            ],
   202            "keys": [
   203              {
   204                "name": "primary",
   205                "isUnique": false,
   206                "columnNames": [
   207                  "f_id"
   208                ]
   209              },
   210              {
   211                "name": "t_demo_ui_name",
   212                "isUnique": true,
   213                "columnNames": [
   214                  "f_name"
   215                ]
   216              },
   217              {
   218                "name": "i_amount",
   219                "isUnique": false,
   220                "columnNames": [
   221                  "f_amount"
   222                ]
   223              }
   224            ]
   225          }
   226        ]
   227      }
   228    ]
   229  }'
   230  export PROJECTENV='{
   231    "env": [
   232      ["envKey1", "envValue1"],
   233      ["envKey2", "envValue2"],
   234      ["envKey3", "envValue3"]
   235    ]
   236  }'
   237  export PROJECTFLOW='{
   238    "source": {"strategies": ["flow_poc"]},
   239    "operators": [
   240        {"opType": "FILTER", "wasmFunc": "filterAge"}, 
   241        {"opType": "MAP", "wasmFunc": "mapTax"}, 
   242        {"opType": "WINDOW", "wasmFunc": "groupByAge"},
   243        {"opType": "GROUP", "wasmFunc": "groupByAge"},
   244        {"opType": "REDUCE", "wasmFunc": "reduce"}
   245    ],
   246    "sink": {
   247        "sinkType": "RMDB", 
   248        "sinkInfo": {
   249            "DBInfo": {
   250                "endpoint": "postgres://test_user:test_passwd@127.0.0.1:5432/test?sslmode=disable" , 
   251                "DBType": "postgres", 
   252                "table": "customer", 
   253                "columns": ["id", "firstName", "lastName", "age", "taxNumber", "city"]
   254            }
   255        }
   256    } 
   257  }'
   258  echo '{"name":"'$PROJECTNAME'","database": '$PROJECTDATABASE',"envs":'$PROJECTENV',"flow": '$PROJECTFLOW'}' | http post :8888/srv-applet-mgr/v0/project -A bearer -a $TOK
   259  ```
   260  
   261  You can define your own database model.
   262  
   263  `schemas` defines database schema structure
   264  
   265  `schemas[i].schema` defines schema name, default using `public` schema
   266  
   267  `schemas[i].tables` defines table structures in schema.
   268  
   269  `schemas[i].tables[i].name` defines table name(required)
   270  
   271  `schemas[i].tables[i].desc` defines table description
   272  
   273  `schemas[i].tables[i].cols` defines table columns
   274  
   275  `schemas[i].tables[i].cols[i].name` defines column name
   276  
   277  `schemas[i].tables[i].cols[i].constrains.datatype` defines column datatype
   278  
   279  > column datatype
   280  
   281  | column datatype | postgres datatype |
   282  |:----------------|:------------------|
   283  | "INT"           | integer           |
   284  | "INT8"          | integer           |
   285  | "INT16"         | integer           |
   286  | "INT32"         | integer           |
   287  | "INT64"         | bigint            |
   288  | "UINT"          | integer           |
   289  | "UINT8"         | integer           |
   290  | "UINT16"        | integer           |
   291  | "UINT32"        | integer           |
   292  | "UINT64"        | bigint            |
   293  | "FLOAT32"       | real              |
   294  | "FLOAT64"       | double precision  |
   295  | "TEXT"          | character varying |
   296  | "BOOL"          | boolean           |
   297  | "TIMESTAMP"     | bigint            |
   298  | "DECIMAL"       | numeric           |
   299  | "NUMERIC"       | numeric           |
   300  
   301  > the timestamp stored in database using epoch timestamp (microsecond)
   302  
   303  `schemas[i].tables[i].cols[i].constrains.datatype` defines column datatype
   304  
   305  `schemas[i].tables[i].cols[i].constrains.length` defines `character varying`
   306  length or `numeric` precision
   307  
   308  `schemas[i].tables[i].cols[i].constrains.decimal` defines `numeric` scale
   309  
   310  `schemas[i].tables[i].cols[i].constrains.default` defines column default value
   311  
   312  `schemas[i].tables[i].cols[i].constrains.null` defines if column can be null
   313  
   314  `schemas[i].tables[i].cols[i].constrains.autoincrement` defines if column is
   315  autoincrement
   316  
   317  > when column is autoincrement, integer defined as `serial` and bigint defined
   318  > as `bigserial` in postgres datatype
   319  
   320  `schemas[i].tables[i].cols[i].constrains.desc` column description
   321  
   322  `schemas[i].tables[i].keys[i].name` defines index name
   323  
   324  `schemas[i].tables[i].keys[i].isUnique` defines if index is unique
   325  
   326  `schemas[i].tables[i].keys[i].columnNames` index related column names
   327  
   328  > NOTE:
   329  > if the key's name is `primary` or has suffix `pkey`, it defined as primary key
   330  > of the table.
   331  > the index name will be built by this pattern:
   332  > 1. non-primary index: `tableName_[i|ui]_[columnName1]_[columnName2]_...`. if
   333       it is a unique index use `ui`, otherwise use `i` to split table name and
   334       index defines.
   335  > 2. primary key: `tableName_primary`
   336  
   337  
   338  output like:
   339  
   340  ```json
   341  {
   342    "accountID": "11276794515805192",
   343    "channelState": true,
   344    "createdAt": "2023-05-03T06:44:05.132275513Z",
   345    "database": {
   346      "schemas": [
   347        {
   348          "schema": "public",
   349          "tables": [
   350            {
   351              "cols": [
   352                {
   353                  "constrains": {
   354                    "autoincrement": true,
   355                    "datatype": "INT64",
   356                    "desc": "primary id"
   357                  },
   358                  "name": "f_id"
   359                },
   360                {
   361                  "constrains": {
   362                    "datatype": "TEXT",
   363                    "desc": "name",
   364                    "length": 255
   365                  },
   366                  "name": "f_name"
   367                },
   368                {
   369                  "constrains": {
   370                    "datatype": "FLOAT64",
   371                    "desc": "amount"
   372                  },
   373                  "name": "f_amount"
   374                },
   375                {
   376                  "constrains": {
   377                    "datatype": "DECIMAL",
   378                    "decimal": 512,
   379                    "default": "0",
   380                    "desc": "income",
   381                    "length": 512
   382                  },
   383                  "name": "f_income"
   384                },
   385                {
   386                  "constrains": {
   387                    "datatype": "TEXT",
   388                    "default": "''",
   389                    "desc": "comment",
   390                    "null": true
   391                  },
   392                  "name": "f_comment"
   393                }
   394              ],
   395              "desc": "demo table",
   396              "keys": [
   397                {
   398                  "columnNames": [
   399                    "f_id"
   400                  ],
   401                  "name": "primary"
   402                },
   403                {
   404                  "columnNames": [
   405                    "f_name"
   406                  ],
   407                  "isUnique": true,
   408                  "name": "t_demo_ui_name"
   409                },
   410                {
   411                  "columnNames": [
   412                    "f_amount"
   413                  ],
   414                  "name": "i_amount"
   415                }
   416              ],
   417              "name": "t_demo"
   418            }
   419          ]
   420        }
   421      ]
   422    },
   423    "envs": {
   424      "env": [
   425        [
   426          "envKey1",
   427          "envValue1"
   428        ],
   429        [
   430          "envKey2",
   431          "envValue2"
   432        ],
   433        [
   434          "envKey3",
   435          "envValue3"
   436        ]
   437      ]
   438    },
   439    "name": "demo2",
   440    "projectID": "11276843314064388",
   441    "updatedAt": "2023-05-03T06:44:05.132275805Z"
   442  }
   443  ```
   444  
   445  ### Create or update project configurations after project created
   446  
   447  ```sh
   448  echo $PROJECTENV | http post :8888/srv-applet-mgr/v0/project_config/x/$PROJECTNAME/PROJECT_ENV -A bearer -a $TOK
   449  echo $PROJECTDATABASE | http post :8888/srv-applet-mgr/v0/project_config/x/$PROJECTNAME/PROJECT_DATABASE -A bearer -a $TOK
   450  echo $PROJECTFLOW | http post :8888/srv-applet-mgr/v0/project_config/x/$PROJECTNAME/PROJECT_FLOW -A bearer -a $TOK
   451  ```
   452  
   453  ### Review your projects and project configurations
   454  
   455  ```shell
   456  http get :8888/srv-applet-mgr/v0/project/x/$PROJECTNAME/data -A bearer -a $TOK ## fetch project by name
   457  http get :8888/srv-applet-mgr/v0/project_config/x/demo/PROJECT_ENV -A bearer -a $TOK  # fetch project env configuration
   458  http get :8888/srv-applet-mgr/v0/project_config/x/demo/PROJECT_DATABASE -A bearer -a $TOK  # fetch project database configuration
   459  http get :8888/srv-applet-mgr/v0/project_config/x/$PROJECTNAME/PROJECT_FLOW -A bearer -a $TOK  # fetch project database configuration
   460  http get :8888/srv-applet-mgr/v0/project/datalist -A bearer -a $TOK # fetch project list you created
   461  ```
   462  
   463  ### Create and deploy applet under project created previously
   464  
   465  ```sh
   466  export WASMFILE=build/wasms/log.wasm
   467  export WASMNAME=log.wasm
   468  export APPLETNAME=log
   469  http --form post :8888/srv-applet-mgr/v0/applet/x/$PROJECTNAME file@$WASMFILE info='{"appletName":"'$APPLETNAME'","wasmName":"'$WASMNAME'"}' -A bearer -a $TOK 
   470  ```
   471  
   472  output like
   473  
   474  ```json
   475  {
   476    "appletID": "11276843999120385",
   477    "createdAt": "2023-05-03T06:55:14.131370253Z",
   478    "instance": {
   479      "appletID": "11276843999120385",
   480      "createdAt": "2023-05-03T06:55:14.146653045Z",
   481      "instanceID": "11276843999135746",
   482      "state": "STARTED",
   483      "updatedAt": "2023-05-03T06:55:14.146653128Z"
   484    },
   485    "name": "11276843999120386",
   486    "projectID": "11276843314064388",
   487    "resource": {
   488      "createdAt": "2023-05-03T06:55:14.112226878Z",
   489      "md5": "30b11f90b1d7453474496f5cc42f0869",
   490      "path": "30b11f90b1d7453474496f5cc42f0869",
   491      "resourceID": "11276843999092744",
   492      "updatedAt": "2023-05-03T06:55:14.112227086Z"
   493    },
   494    "resourceID": "11276843999092744",
   495    "updatedAt": "2023-05-03T06:55:14.131370336Z"
   496  }
   497  ```
   498  
   499  > you can create applet with deploy state and event routing strategy, if no
   500  > strategy configuration, the default
   501  > strategy with `DEFAULT` event type and `start` handler will be created
   502  
   503  `info.appletName` defined the unique applet name under the project
   504  
   505  `info.wasmName` the resource filename
   506  
   507  `info.wasmMd5` the wasm file md5, if it is not empty, w3bstream node will check
   508  md5 sum
   509  
   510  `info.wasmCache` wasm cache config
   511  
   512  `info.wasmCache.mode` cache mode, enumerated in `MEMORY` and `REDIS`, `MEMORY`
   513  is default
   514  
   515  `info.strategies` event routing strategies
   516  
   517  `info.strategies[i].eventType` routing with eventType (user defined)
   518  
   519  `info.strategies[i].handler` routing wasm handler name (wasm exported)
   520  
   521  ### Create instance of the applet you created before
   522  
   523  ```sh
   524  export APPLETID=11276843999120385 ## created before
   525  http post :8888/srv-applet-mgr/v0/deploy/applet/$APPLETID -A bearer -a $TOK
   526  ## with cache config
   527  export WASMCACHECONFIG='{"cache":{"mode": "REDIS"}}'
   528  echo $WASMCACHECONFIG | http post :8888/srv-applet-mgr/v0/deploy/applet/$APPLETID -A bearer -a $TOK
   529  ```
   530  
   531  output like
   532  
   533  ```json
   534  {
   535    "appletID": "11276843999120385",
   536    "createdAt": "2023-05-03T07:13:28.409513718Z",
   537    "instanceID": "11276845119659014",
   538    "state": "CREATED",
   539    "updatedAt": "2023-05-03T07:13:28.409514176Z"
   540  }
   541  ```
   542  
   543  if the instance is already created, output like
   544  
   545  ```json
   546  {
   547    "canBeTalk": true,
   548    "code": 409999008,
   549    "desc": "11276843999120385",
   550    "fields": null,
   551    "id": "",
   552    "key": "MultiInstanceDeployed",
   553    "msg": "Multi Instance Deployed",
   554    "sources": [
   555      "srv-applet-mgr@v1.1.0-rc3-6-gbf5cbc0"
   556    ]
   557  }
   558  ```
   559  
   560  ### Control instance
   561  
   562  ```sh
   563  export INSTANCEID=11276845119659014 ## created before
   564  export DEPLOYCMD=START
   565  http put :8888/srv-applet-mgr/v0/deploy/$INSTANCEID/$DEPLOYCMD -A bearer -a $TOK
   566  ```
   567  
   568  deploy command enumerated in `START` and `HUNGUP`
   569  
   570  `START` change the instance state to `STARTED`
   571  
   572  `HUNGUP` change the instance state to `STOPPED`
   573  
   574  ### Update applet and redeploy instance
   575  
   576  ```sh
   577  http --form put :8888/srv-applet-mgr/v0/applet/$APPLETID file@$WASMFILE info='{"appletName":"'$APPLETNAME'","wasmName":"'$WASMNAME'","start":true}' -A bearer -a $TOK
   578  ```
   579  
   580  ### Register publisher
   581  
   582  ```sh
   583  export PUBNAME=mobile    # device name
   584  export PUBKEY=mn20130503 # device unique identity, usually it is device's machine number or serial number
   585  echo '{"name":"'$PUBNAME'", "key":"'$PUBKEY'"}' | http post :8888/srv-applet-mgr/v0/publisher/x/$PROJECTNAME -A bearer -a $TOK
   586  ```
   587  
   588  output like
   589  
   590  ```sh
   591  {
   592      "createdAt": "2023-05-03T16:13:16.343103+08:00",
   593      "key": "mn20130503",
   594      "name": "mobile",
   595      "projectID": "11276843314064388",
   596      "publisherID": "155392036869560322",
   597      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJQYXlsb2FkIjoiMTU1MzkyMDM2ODY5NTYwMzIyIiwiaXNzIjoiaW90ZXgtdzNic3RyZWFtIn0.OHME3ij5MaJcvekctgYvosQ8DIo-K-guQbYPbQAdyYo",
   598      "updatedAt": "2023-05-03T16:13:16.343103+08:00"
   599  }
   600  ```
   601  
   602  > the `token` responded is used for validating publisher when publishing event.
   603  
   604  ### Register publisher if not exists
   605  
   606  ```sh
   607  export PUBNAME=mobile    # device name
   608  export PUBKEY=mn20130503 # device unique identity, usually it is device's machine number or serial number
   609  echo '{"name":"'$PUBNAME'", "key":"'$PUBKEY'"}' | http post :8888/srv-applet-mgr/v0/publisher/x/{projectName}/upsert -A bearer -a $TOK
   610  ```
   611  
   612  output like
   613  
   614  ```sh
   615  {
   616      "createdAt": "2023-05-03T16:13:16.343103+08:00",
   617      "key": "mn20130503",
   618      "name": "mobile",
   619      "projectID": "11276843314064388",
   620      "publisherID": "155392036869560322",
   621      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJQYXlsb2FkIjoiMTU1MzkyMDM2ODY5NTYwMzIyIiwiaXNzIjoiaW90ZXgtdzNic3RyZWFtIn0.OHME3ij5MaJcvekctgYvosQ8DIo-K-guQbYPbQAdyYo",
   622      "updatedAt": "2023-05-03T16:13:16.343103+08:00"
   623  }
   624  
   625  
   626  ### Review registered publisher
   627  
   628  ```sh
   629  http get :8888/srv-applet-mgr/v0/publisher/x/$PROJECTNAME -A bearer -a $TOK
   630  ```
   631  
   632  output like:
   633  
   634  ```json
   635  {
   636    "data": [
   637      {
   638        "createdAt": "2023-05-03T16:13:16+08:00",
   639        "key": "mn20130503",
   640        "name": "mobile",
   641        "projectID": "11276843314064388",
   642        "publisherID": "155392036869560322",
   643        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJQYXlsb2FkIjoiMTU1MzkyMDM2ODY5NTYwMzIyIiwiaXNzIjoiaW90ZXgtdzNic3RyZWFtIn0.OHME3ij5MaJcvekctgYvosQ8DIo-K-guQbYPbQAdyYo",
   644        "updatedAt": "2023-05-03T16:13:16+08:00"
   645      }
   646    ],
   647    "total": 1
   648  }
   649  ```
   650  
   651  ### Create strategy for applet created before
   652  
   653  Create a strategy of handler in applet and eventType
   654  
   655  ```sh
   656  export EVENTTYPE=mobile_geo
   657  export HANDLER=handle_geo_data
   658  export AUTOCOLLECTMETIC=true
   659  echo '{"appletID":"'$APPLETID'", "eventType":"'$EVENTTYPE'", "handler":"'$HANDLER'", "autoCollectMetric":$AUTOCOLLECTMETIC}' | http post :8888/srv-applet-mgr/v0/strategy/x/$PROJECTNAME -A bearer -a $TOK
   660  ```
   661  
   662  output like:
   663  
   664  ```json
   665  {
   666      "appletID": "155396152440654850",
   667      "autoCollectMetric": true,
   668      "createdAt": "2023-08-07T13:58:32.428387+08:00",
   669      "eventType": "AUTO_COLLECT_METRIC2",
   670      "handler": "start",
   671      "projectID": "155396149977461760",
   672      "strategyID": "155400522057232384",
   673      "updatedAt": "2023-08-07T13:58:32.428387+08:00"
   674  }
   675  ```
   676  
   677  ### Review strategies under current project
   678  
   679  ```sh
   680  http get :8888/srv-applet-mgr/v0/strategy/x/$PROJECTNAME/datalist -A bearer -a $TOK
   681  ```
   682  
   683  output like:
   684  
   685  ```json
   686  {
   687    "data": [
   688      {
   689        "appletID": "11276843999120385",
   690        "createdAt": "2023-05-03T16:17:40+08:00",
   691        "eventType": "mobile_geo",
   692        "handler": "handle_geo_data",
   693        "projectID": "11276843314064388",
   694        "strategyID": "155392037140510721",
   695        "updatedAt": "2023-05-03T16:17:40+08:00"
   696      },
   697      {
   698        "appletID": "11276843999120385",
   699        "createdAt": "2023-05-03T14:55:14+08:00",
   700        "eventType": "DEFAULT",
   701        "handler": "start",
   702        "projectID": "11276843314064388",
   703        "strategyID": "11276843999125505",
   704        "updatedAt": "2023-05-03T14:55:14+08:00"
   705      }
   706    ],
   707    "total": 2
   708  }
   709  ```
   710  
   711  ### Publish event through http
   712  
   713  ```sh
   714  export TOPIC=${pub_topic} ## intact project name(required)
   715  export PUBTOK=${pub_token} ## created before(required)
   716  export EVENTTYPE=mobile_geo # default means start handler
   717  export EVENTID=`uuidgen` ## this id is used for tracing event(recommended)
   718  export PAYLOAD=${payload} ## set your payload
   719  export TIMESTAMP=`date +%s` ## event pub timestamp(recommended)
   720  http post :8889/srv-applet-mgr/v0/event/$TOPIC\?eventType=$EVENTTYPE\&eventID=$EVENTID\&timestamp=$TIMESTAMP --raw=$PAYLOAD -A bearer -a $PUBTOK
   721  ```
   722  
   723  > note event handler service using 8889 for default
   724  
   725  output like
   726  
   727  ```json
   728  {
   729    "channel": "aid_11276794515805192_demo2",
   730    "eventID": "3d5d76d6-24be-4e47-9f44-cac2b4855e1a_w3b",
   731    "publisherID": "155392036869560322",
   732    "results": [
   733      {
   734        "appletName": "log",
   735        "code": -1,
   736        "error": "instance not running",
   737        "handler": "handle_geo_data",
   738        "instanceID": "11276845119659014",
   739        "returnValue": null
   740      }
   741    ]
   742  }
   743  ```
   744  
   745  ### Publish event through mqtt (use `pub_client` CLI)
   746  
   747  #### Use namespace only
   748  
   749  ```sh
   750  export MQTT_HOST=localhost
   751  export MQTT_PORT=1883
   752  export MQTT_USERNAME=username
   753  export MQTT_PASSWORD=password
   754  ./pub_client -topic $TOPIC -token $PUBTOK -data $PAYLOAD -host $MQTT_HOST -port $MQTT_PORT -usernmae $MQTT_USERNAME -password $MQTT_PASSWORD
   755  ```
   756  
   757  #### Use more information in topic
   758  
   759  ```sh
   760  export MQTT_HOST=localhost
   761  export MQTT_PORT=1883
   762  export MQTT_USERNAME=
   763  export MQTT_PASSWORD=
   764  export TOPIC="$PROJECTNAME/push/$PUB_TOK/$EVENTTYPE/ts=$(date +%s)&id=$(uuidgen)"
   765  export PAYLOAD=$(input your payload)
   766  export MN=$(input your device mn)
   767  ./pub_client -mn $MN -topic $TOPIC -data $PAYLOAD -wait 10
   768  
   769  ```
   770  
   771  `pub_client` will send payload to topic you assigned, and wait 10 second from topic `ack/$MN` for ack
   772  
   773  output like
   774  
   775  ```text
   776  >>>> message published
   777  receive ack from ack/mn-LOCOL-DEV
   778  <<<< message ack received
   779  {
   780    "channel": "aid_155396149766916097_sincos",
   781    "publisherID": "155400623279265799",
   782    "publisherKey": "mn-LOCAL-DEV",
   783    "eventID": "4CAD8CC1-B2FC-4E00-BA31-55E2E7518D29",
   784    "results": [
   785      {
   786        "appletName": "155396152440654851",
   787        "instanceID": "155396152440662018",
   788        "handler": "start",
   789        "returnValue": null,
   790        "code": 0
   791      }
   792    ]
   793  }
   794  ```
   795  
   796  server log like
   797  
   798  ```json
   799  {
   800    "@lv": "info",
   801    "@prj": "srv-applet-mgr",
   802    "@ts": "20221017-092252.877+08:00",
   803    "msg": "sub handled",
   804    "payload": {
   805      "payload": "..."
   806    }
   807  }
   808  ```
   809  
   810  the `pub_client` sends event message through mqtt broker using protobuf
   811  encoding. the event defined as follows
   812  
   813  | field name       | protobuf filed    | protobuf seq | datatype | requirement | comment                                                                            |
   814  |:-----------------|:------------------|:-------------|:---------|:------------|:-----------------------------------------------------------------------------------|
   815  | Header           | header            | 1            | object   | required    |                                                                                    |
   816  | Header.EventType | header.event_type | header.1     | string   | recommended | event type(user defined) for event routing, according to strategies created before |
   817  | Header.PubId     | header.pub_id     | header.2     | string   | recommended | publisher id, usually it is the device machine number, you register before         |
   818  | Header.Token     | header.token      | header.3     | string   | required    | publisher token. it contains the publisher id (or DID)                             |
   819  | Header.PubTime   | header.pub_time   | header.4     | int64    | recommended | message timestamp when published, use unix epoch timestamp (in UTC)                |
   820  | Header.EventId   | header.event_id   | header.5     | string   | recommended | event id is the unique identity of this message related with the publisher         |
   821  | Payload          | payload           | 2            | bytes    | -           | message payload                                                                    |
   822  
   823  ### Data cleanup
   824  
   825  Be careful.
   826  It will delete anything in the project, contains applet, publisher, strategy
   827  etc.
   828  
   829  ```sh
   830  ## delete project, all configurations in the project, contains applet, publisher,
   831  ## strategy and instances will be deleted, the database model will be kept.
   832  http delete :8888/srv-applet-mgr/v0/project/x/$PROJECTNAME -A bearer -a $TOK
   833  ## delete applet, all instances, strategy and the configurations will be deleted
   834  http delete :8888/srv-applet-mgr/v0/applet/data/$APPLETID -A bearer -a $TOK
   835  ## delete instance, the instance will be released from host memory and the configurations
   836  ## will be deleted.
   837  http delete :8888/srv-applet-mgr/v0/deploy/data/$INSTANCEID -A bearer -a $TOK
   838  ```
   839  
   840  ### Post blockchain contract event log monitor
   841  
   842  ```sh
   843  echo '{"eventType": "DEFAULT", "chainID": 4690, "contractAddress": "${contractAddress}","blockStart": ${blockStart},"blockEnd": ${blockEnd},"topic0":"${topic0}"}' | http :8888/srv-applet-mgr/v0/monitor/x/$PROJECTNAME/contract_log -A bearer -a $TOK
   844  ```
   845  
   846  output like
   847  
   848  ```json
   849  {
   850    "blockCurrent": 16737070,
   851    "blockEnd": 16740080,
   852    "blockStart": 16737070,
   853    "chainID": 4690,
   854    "contractAddress": "${contractAddress}",
   855    "contractlogID": "2162022028435556",
   856    "createdAt": "2022-10-19T21:21:30.220198+08:00",
   857    "eventType": "ANY",
   858    "projectName": "${projectName}",
   859    "topic0": "${topic0}",
   860    "updatedAt": "2022-10-19T21:21:30.220198+08:00"
   861  }
   862  ```
   863  
   864  delete it
   865  
   866  ```sh
   867  export CONTRACTLOGID=${contractlogID}
   868  http delete :8888/srv-applet-mgr/v0/monitor/x/$PROJECTNAME/contract_log/$CONTRACTLOGID -A bearer -a $TOK
   869  ```
   870  
   871  ### Post blockchain transaction monitor
   872  
   873  ```sh
   874  echo '{"eventType": "DEFAULT", "chainID": 4690, "txAddress": "${txAddress}"}' | http :8888/srv-applet-mgr/v0/monitor/x/$PROJECTNAME/chain_tx -A bearer -a $TOK
   875  ```
   876  
   877  output like
   878  
   879  ```json
   880  {
   881    "chainID": 4690,
   882    "chaintxID": "2724127039316068",
   883    "createdAt": "2022-10-21T10:35:06.498594+08:00",
   884    "eventType": "ANY",
   885    "projectName": "testproject",
   886    "txAddress": "${txAddress}",
   887    "updatedAt": "2022-10-21T10:35:06.498594+08:00"
   888  }
   889  ```
   890  
   891  delete it
   892  
   893  ```sh
   894  export CHAINTXID=${chaintxID}
   895  http delete :8888/srv-applet-mgr/v0/monitor/x/$PROJECTNAME/chain_tx/$CHAINTXID -A bearer -a $TOK
   896  ```
   897  
   898  ### Post blockchain height monitor
   899  
   900  ```sh
   901  echo '{"eventType": "DEFAULT", "chainID": 4690, "height": ${height}}' | http :8888/srv-applet-mgr/v0/monitor/x/$PROJECTNAME/chain_height -A bearer -a $TOK
   902  ```
   903  
   904  output like
   905  
   906  ```json
   907  {
   908    "chainHeightID": "2727219570933860",
   909    "chainID": 4690,
   910    "createdAt": "2022-10-21T10:47:23.815552+08:00",
   911    "eventType": "ANY",
   912    "height": 16910805,
   913    "projectName": "testproject",
   914    "updatedAt": "2022-10-21T10:47:23.815553+08:00"
   915  }
   916  ```
   917  
   918  delete it
   919  
   920  ```sh
   921  export CHAINHEIGHTID=${chainHeightID}
   922  http delete :8888/srv-applet-mgr/v0/monitor/x/$PROJECTNAME/chain_height/$CHAINHEIGHTID -A bearer -a $TOK
   923  ```
   924  
   925  ### Create operator
   926  
   927  ```sh
   928  export OPERATORNAME=${operator_name}
   929  export PRIVATEKEY=${private_key}
   930  echo '{"name":"'$OPERATORNAME'","privateKey":"'$PRIVATEKEY'"}' | http post :8888/srv-applet-mgr/v0/operator -A bearer -a $TOK
   931  ```
   932  
   933  output like
   934  
   935  ```json
   936  {
   937    "accountID": "9221139481037349891",
   938    "createdAt": "2023-05-23T13:30:00.11819655Z",
   939    "name": "myoperator",
   940    "operatorID": "11278637725570052",
   941    "updatedAt": "2023-05-23T13:30:00.118200425Z"
   942  }
   943  ```
   944  
   945  list all operators
   946  
   947  ```sh
   948  http get :8888/srv-applet-mgr/v0/operator/datalist -A bearer -a $TOK
   949  ```
   950  
   951  delete it
   952  
   953  ```sh
   954  export OPERATORID=${operatorID}
   955  http delete :8888/srv-applet-mgr/v0/operator/data/$OPERATORID -A bearer -a $TOK
   956  ```
   957  
   958  ### Create project operator
   959  
   960  ```sh
   961  export PROJECTID=${project_id}
   962  http post :8888/srv-applet-mgr/v0/project_operator/$PROJECTID/$OPERATORID -A bearer -a $TOK
   963  ```
   964  
   965  output like
   966  
   967  ```json
   968  {
   969    "createdAt": "2023-05-23T13:32:03.918223385Z",
   970    "operatorID": "11278637725570052",
   971    "projectID": "9221139481524034564",
   972    "updatedAt": "2023-05-23T13:32:03.918233052Z"
   973  }
   974  ```
   975  
   976  get project operator
   977  
   978  ```sh
   979  http get :8888/srv-applet-mgr/v0/project_operator/data/$PROJECTID -A bearer -a $TOK
   980  ```
   981  
   982  delete it
   983  
   984  ```sh
   985  http delete :8888/srv-applet-mgr/v0/project_operator/$PROJECTID -A bearer -a $TOK
   986  ```
   987  
   988  ## List API Group Meta List
   989  
   990  This API is used to list all API functional groups, with its name and description
   991  
   992  ```sh
   993  http get :8888/srv-applet-mgr/v0/account_access_key/operator_group_metas -A bearer -a $TOK
   994  ```
   995  
   996  ```json
   997  [
   998    {
   999      "desc": "View and manage account",
  1000      "name": "Account"
  1001    },
  1002    {
  1003      "desc": "View and manage access token",
  1004      "name": "Account Access Key"
  1005    },
  1006    {
  1007      "desc": "Account register",
  1008      "name": "Account Register"
  1009    }
  1010  ]
  1011  ```
  1012  
  1013  ## Create Account Access Key (with privileges)
  1014  
  1015  ```sh
  1016  export KEY_NAME=key_name
  1017  export KEY_DESC=desc
  1018  export KEY_EXPIRATION_DAYS=30 # if expiration days is 0, this key will be not expired.
  1019  
  1020  # List all group metas through command above to fetch group name
  1021  # and the perm is a string enum: "NO_ACCESS", "READONLY" and "READ_WRITE"
  1022  export KEY_PRIVILEGES='[{"name":"Account", "perm":"READ_WRITE"},{"name":"Account Access Key", "perm":"NO_ACCESS"}, {"name":"Project", "perm":"READONLY"}]'
  1023  
  1024  echo '{"name":"'$KEY_NAME'", "expirationDays": $KEY_EXPIRATION_DAYS, "desc": "'$KEY_DESC'","privileges":'$KEY_PRIVILEGES'}' | http post :8888/srv-applet-mgr/v0/account_access_key -A bearer -a $TOK
  1025  ```
  1026  
  1027  output like
  1028  
  1029  ```json
  1030  {
  1031    "accessKey": "w3b_xxxx",
  1032    "desc": "desc",
  1033    "expiredAt": "2023-07-21T08:13:08.592213Z",
  1034    "name": "key_name",
  1035    "privileges": [
  1036      {
  1037        "desc": "View and manage project blockchain operator",
  1038        "name": "Project Operator",
  1039        "perm": "NO_ACCESS"
  1040      },
  1041      {
  1042        "desc": "View and manage project config",
  1043        "name": "Project Config",
  1044        "perm": "NO_ACCESS"
  1045      },
  1046      {
  1047        "desc": "View and manage applet",
  1048        "name": "Applet",
  1049        "perm": "NO_ACCESS"
  1050      }
  1051    ]
  1052  }
  1053  ```
  1054  
  1055  ## Update Account Access Key (with privileges)
  1056  
  1057  ```sh
  1058  export KEY_NAME=key_name
  1059  export KEY_DESC=desc
  1060  export KEY_EXPIRATION_DAYS=30
  1061  export KEY_PRIVILEGES='[{"name":"Account", "perm":"READ_WRITE"},{"name":"Account Access Key", "perm":"NO_ACCESS"}, {"name":"Project", "perm":"READONLY"}]'
  1062  
  1063  echo '{"expirationDays":'$KEY_EXPIRATION_DAYS', "desc":"'$KEY_DESC'", "privileges":'$KEY_PRIVILEGES'}' | http put :8888/srv-applet-mgr/v0/account_access_key/$KEY_NAME -A bearer -a $TOK
  1064  ```
  1065  
  1066  output like
  1067  
  1068  ```json
  1069  {
  1070    "desc": "test access",
  1071    "expiredAt": "2023-08-19T01:01:43.847047Z",
  1072    "identityID": "155396149766916097",
  1073    "identityType": "ACCOUNT",
  1074    "lastUsed": "2023-07-20T08:46:28+08:00",
  1075    "name": "test",
  1076    "privileges": [
  1077      {
  1078        "desc": "View and manage project blockchain operator",
  1079        "name": "Project Operator",
  1080        "perm": "NO_ACCESS"
  1081      },
  1082      {
  1083        "desc": "View and manage project config",
  1084        "name": "Project Config",
  1085        "perm": "NO_ACCESS"
  1086      },
  1087      {
  1088        "desc": "View and manage applet",
  1089        "name": "Applet",
  1090        "perm": "NO_ACCESS"
  1091      }
  1092    ]
  1093  }
  1094  ```
  1095  
  1096  ## Delete Access Key
  1097  
  1098  ```sh
  1099  export KEY_NAME=key_name
  1100  http delete :8888/srv-applet-mgr/v0/account_access_key/$KEY_NAME -A bearer -a $TOK
  1101  
  1102  ```
  1103  
  1104  ## List Access Key
  1105  
  1106  ```sh
  1107  http get :8888/srv-applet-mgr/v0/account_access_key/datalist -A bearer -a $TOK
  1108  ```
  1109  
  1110  output like
  1111  
  1112  ```json
  1113  {
  1114    "data": [
  1115      {
  1116        "createdAt": "2023-07-03T05:01:25+08:00",
  1117        "desc": "desc",
  1118        "lastUsed": "2023-07-03T05:03:22+08:00",
  1119        "name": "test",
  1120        "updatedAt": "2023-07-03T05:03:22+08:00",
  1121        "privileges": [
  1122          {
  1123            "desc": "View and manage project blockchain operator",
  1124            "name": "Project Operator",
  1125            "perm": "NO_ACCESS"
  1126          },
  1127          {
  1128            "desc": "View and manage project config",
  1129            "name": "Project Config",
  1130            "perm": "NO_ACCESS"
  1131          },
  1132          {
  1133            "desc": "View and manage applet",
  1134            "name": "Applet",
  1135            "perm": "NO_ACCESS"
  1136          }
  1137        ]
  1138      }
  1139    ],
  1140    "total": 1
  1141  }
  1142  ```