diff --git a/Makefile b/Makefile index ceebfe3c2..0ce13b9ff 100644 --- a/Makefile +++ b/Makefile @@ -433,7 +433,7 @@ docker-liteprotocoltester-push: ################ ## C Bindings ## ################ -.PHONY: cbindings cwaku_example libwaku liblmapi +.PHONY: cbindings cwaku_example libwaku liblmapi liblmapi_example STATIC ?= 0 LIBWAKU_BUILD_COMMAND ?= libwakuDynamic @@ -463,6 +463,31 @@ libwaku: | build deps librln liblmapi: | build deps librln echo -e $(BUILD_MSG) "build/$@.$(LIB_EXT)" && $(ENV_SCRIPT) nim $(LMAPI_BUILD_COMMAND) $(NIM_PARAMS) waku.nims $@.$(LIB_EXT) +liblmapi_example: | build liblmapi + @echo -e $(BUILD_MSG) "build/$@" +ifeq ($(detected_OS),Darwin) + gcc -o build/$@ \ + liblmapi/examples/liblmapi_example.c \ + -I./liblmapi \ + -L./build \ + -llmapi \ + -Wl,-rpath,./build +else ifeq ($(detected_OS),Linux) + gcc -o build/$@ \ + liblmapi/examples/liblmapi_example.c \ + -I./liblmapi \ + -L./build \ + -llmapi \ + -Wl,-rpath,'$$ORIGIN' +else ifeq ($(detected_OS),Windows) + gcc -o build/$@.exe \ + liblmapi/examples/liblmapi_example.c \ + -I./liblmapi \ + -L./build \ + -llmapi \ + -lws2_32 +endif + ##################### ## Mobile Bindings ## ##################### diff --git a/liblmapi/BUILD.md b/liblmapi/BUILD.md new file mode 100644 index 000000000..0a8422f58 --- /dev/null +++ b/liblmapi/BUILD.md @@ -0,0 +1,165 @@ +# Building liblmapi and Examples + +## Prerequisites + +- Nim 2.x compiler +- Rust toolchain (for RLN dependencies) +- GCC or Clang compiler +- Make + +## Building the Library + +### Dynamic Library + +```bash +make liblmapi +``` + +This creates `build/liblmapi.dylib` (macOS) or `build/liblmapi.so` (Linux). + +### Static Library + +```bash +nim liblmapiStatic +``` + +This creates `build/liblmapi.a`. + +## Building Examples + +### liblmapi Example + +Compile the C example that demonstrates all library features: + +```bash +# Using Make (recommended) +make liblmapi_example + +# Or manually on macOS: +gcc -o build/liblmapi_example \ + liblmapi/examples/liblmapi_example.c \ + -I./liblmapi \ + -L./build \ + -llmapi \ + -Wl,-rpath,./build + +# Or manually on Linux: +gcc -o build/liblmapi_example \ + liblmapi/examples/liblmapi_example.c \ + -I./liblmapi \ + -L./build \ + -llmapi \ + -Wl,-rpath='$ORIGIN' +``` + +## Running Examples + +```bash +./build/liblmapi_example +``` + +The example will: +1. Create a Logos Messaging node +2. Register event callbacks for message events +3. Start the node +4. Subscribe to a content topic +5. Send a message +6. Show message delivery events (sent, propagated, or error) +7. Unsubscribe and cleanup + +## Build Artifacts + +After building, you'll have: + +``` +build/ +├── liblmapi.dylib # Dynamic library (34MB) +├── liblmapi.dylib.dSYM/ # Debug symbols +└── liblmapi_example # Compiled example (34KB) +``` + +## Library Headers + +The main header file is: +- `liblmapi/liblmapi.h` - C API declarations + +## Troubleshooting + +### Library not found at runtime + +If you get "library not found" errors when running the example: + +**macOS:** +```bash +export DYLD_LIBRARY_PATH=/path/to/build:$DYLD_LIBRARY_PATH +./build/liblmapi_example +``` + +**Linux:** +```bash +export LD_LIBRARY_PATH=/path/to/build:$LD_LIBRARY_PATH +./build/liblmapi_example +``` + +### Compilation fails + +Make sure you've run: +```bash +make update +``` + +This updates all git submodules which are required for building. + +## Static Linking + +To link statically instead of dynamically: + +```bash +gcc -o build/simple_example \ + liblmapi/examples/simple_example.c \ + -I./liblmapi \ + build/liblmapi.a \ + -lm -lpthread +``` + +Note: Static library is much larger (~129MB) but creates a standalone executable. + +## Cross-Compilation + +For cross-compilation, you need to: +1. Build the Nim library for the target platform +2. Use the appropriate cross-compiler +3. Link against the target platform's liblmapi + +Example for Linux from macOS: +```bash +# Build library for Linux (requires Docker or cross-compilation setup) +# Then compile with cross-compiler +``` + +## Integration with Your Project + +### CMake + +```cmake +find_library(LMAPI_LIBRARY NAMES lmapi PATHS ${PROJECT_SOURCE_DIR}/build) +include_directories(${PROJECT_SOURCE_DIR}/liblmapi) +target_link_libraries(your_target ${LMAPI_LIBRARY}) +``` + +### Makefile + +```makefile +CFLAGS += -I/path/to/liblmapi +LDFLAGS += -L/path/to/build -llmapi -Wl,-rpath,/path/to/build + +your_program: your_program.c + $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) +``` + +## API Documentation + +See: +- [liblmapi.h](liblmapi/liblmapi.h) - API function declarations +- [MESSAGE_EVENTS.md](liblmapi/MESSAGE_EVENTS.md) - Message event handling guide +- [IMPLEMENTATION_SUMMARY.md](liblmapi/IMPLEMENTATION_SUMMARY.md) - Implementation details diff --git a/liblmapi/IMPLEMENTATION_SUMMARY.md b/liblmapi/IMPLEMENTATION_SUMMARY.md new file mode 100644 index 000000000..3b410de45 --- /dev/null +++ b/liblmapi/IMPLEMENTATION_SUMMARY.md @@ -0,0 +1,155 @@ +# liblmapi - Summary + +## Overview + +Created a new C FFI library `liblmapi` (Logos Messaging API) that provides a simplified interface to the high-level API functions from `waku/api/api.nim`. + +## Files Created + +### Core Library Files + +1. **liblmapi/liblmapi.h** - C header file + - Defines C FFI interface + - Includes function declarations for node lifecycle and messaging + - Return codes and callback typedef + +2. **liblmapi/liblmapi.nim** - Main library entry point + - Imports and includes API modules + - Exports `lmapi_destroy` function + - Follows same pattern as `library/libwaku.nim` + +3. **liblmapi/declare_lib.nim** - Library declaration + - Uses `declareLibrary("lmapi")` macro + - Exports `lmapi_set_event_callback` function + +4. **liblmapi/nim.cfg** - Nim configuration + - Sets up compiler flags (gc:refc, threads:on) + - Configures paths for nim-ffi and project root + - Library-specific build settings + +### API Implementation Files + +5. **liblmapi/lmapi/node_api.nim** - Node lifecycle API + - `lmapi_create_node` - Creates node from JSON config + - `lmapi_start_node` - Starts the node + - `lmapi_stop_node` - Stops the node + - Uses `registerReqFFI` macro for CreateNodeRequest + +6. **liblmapi/lmapi/messaging_api.nim** - Messaging API + - `lmapi_subscribe` - Subscribe to content topic + - `lmapi_unsubscribe` - Unsubscribe from content topic + - `lmapi_send` - Send message with base64-encoded payload + - All use `{.ffi.}` pragma for automatic FFI wrapping + +### Documentation and Examples + +7. **liblmapi/README.md** - Main documentation + - API function reference + - Configuration examples + - Build instructions + - Usage patterns + - Architecture overview + +8. **liblmapi/examples/liblmapi_example.c** - C example program + - Demonstrates all API functions + - Shows proper callback handling + - Complete lifecycle example + +9. **liblmapi/examples/README.md** - Example documentation + - Build instructions per platform + - Expected output + - Usage notes + +### Build System Integration + +10. **Modified waku.nims** + - Added `liblmapiStatic` task + - Added `liblmapiDynamic` task + - Both use `buildLibrary` helper with chronicle params + +11. **Modified Makefile** + - Added `liblmapi` to PHONY targets + - Added `LMAPI_BUILD_COMMAND` variable + - Added `liblmapi` target that calls nim tasks + - Respects STATIC flag for static/dynamic build + +## API Functions + +### Node Lifecycle +- `lmapi_create_node` - Create and configure node +- `lmapi_start_node` - Start node operations +- `lmapi_stop_node` - Stop node operations +- `lmapi_destroy` - Clean up and free resources + +### Messaging +- `lmapi_subscribe` - Subscribe to content topic +- `lmapi_unsubscribe` - Unsubscribe from content topic +- `lmapi_send` - Send message envelope + +### Events +- `lmapi_set_event_callback` - Register event callback + +## Build Commands + +```bash +# Build dynamic library (default) +make liblmapi + +# Build static library +make liblmapi STATIC=1 + +# Or directly via nim +nim liblmapiDynamic waku.nims liblmapi.so +nim liblmapiStatic waku.nims liblmapi.a +``` + +## Key Design Decisions + +1. **Follows libwaku pattern**: Same structure and conventions as existing `library/libwaku.nim` + +2. **Uses nim-ffi framework**: Leverages vendor/nim-ffi for: + - Thread-safe request processing + - Async operation management + - Callback marshaling + - Memory management between C and Nim + +3. **Wraps new high-level API**: Directly wraps `waku/api/api.nim` functions: + - `createNode(config: NodeConfig)` + - `subscribe(w: Waku, contentTopic: ContentTopic)` + - `send(w: Waku, envelope: MessageEnvelope)` + +4. **JSON-based configuration**: Uses JSON for: + - Node configuration (mode, networking, protocols) + - Message envelopes (contentTopic, payload, ephemeral) + - Simplifies C interface while maintaining flexibility + +5. **Base64 payload encoding**: Message payloads must be base64-encoded in JSON + - Avoids binary data issues in JSON + - Standard encoding for C interop + +## Integration Points + +The library integrates with: + +- `waku/api/api.nim` - Main API functions +- `waku/api/api_conf.nim` - Configuration types (NodeConfig, NetworkingConfig, etc.) +- `waku/api/types.nim` - Core types (MessageEnvelope, RequestId, etc.) +- `waku/factory/waku.nim` - Waku instance type +- `vendor/nim-ffi/` - FFI infrastructure + +## Testing + +To test the library: + +1. Build it: `make liblmapi` +2. Build the example: `make liblmapi_example` or `cd liblmapi/examples && gcc -o liblmapi_example liblmapi_example.c -I.. -L../../build -llmapi` +3. Run: `./build/liblmapi_example` + +## Next Steps + +Potential enhancements: +- Add more examples (async, multi-threaded, etc.) +- Add proper test suite +- Add CI/CD integration +- Add mobile platform support (Android/iOS) +- Add language bindings (Python, Go, etc.) diff --git a/liblmapi/MESSAGE_EVENTS.md b/liblmapi/MESSAGE_EVENTS.md new file mode 100644 index 000000000..7c425e7ab --- /dev/null +++ b/liblmapi/MESSAGE_EVENTS.md @@ -0,0 +1,148 @@ +# Message Event Handling in LMAPI + +## Overview + +The LMAPI library emits three types of message delivery events that clients can listen to by registering an event callback using `lmapi_set_event_callback()`. + +## Event Types + +### 1. message_sent +Emitted when a message is successfully accepted by the send service and queued for delivery. + +**JSON Structure:** +```json +{ + "eventType": "message_sent", + "requestId": "unique-request-id", + "messageHash": "0x..." +} +``` + +**Fields:** +- `eventType`: Always "message_sent" +- `requestId`: Request ID returned from the send operation +- `messageHash`: Hash of the message that was sent + +### 2. message_propagated +Emitted when a message has been successfully propagated to neighboring nodes on the network. + +**JSON Structure:** +```json +{ + "eventType": "message_propagated", + "requestId": "unique-request-id", + "messageHash": "0x..." +} +``` + +**Fields:** +- `eventType`: Always "message_propagated" +- `requestId`: Request ID from the send operation +- `messageHash`: Hash of the message that was propagated + +### 3. message_error +Emitted when an error occurs during message sending or propagation. + +**JSON Structure:** +```json +{ + "eventType": "message_error", + "requestId": "unique-request-id", + "messageHash": "0x...", + "error": "error description" +} +``` + +**Fields:** +- `eventType`: Always "message_error" +- `requestId`: Request ID from the send operation +- `messageHash`: Hash of the message that failed +- `error`: Description of what went wrong + +## Usage + +### 1. Define an Event Callback + +```c +void event_callback(int ret, const char *msg, size_t len, void *userData) { + if (ret != RET_OK || msg == NULL || len == 0) { + return; + } + + // Parse the JSON message + // Extract eventType field + // Handle based on event type + + if (eventType == "message_sent") { + // Handle message sent + } else if (eventType == "message_propagated") { + // Handle message propagated + } else if (eventType == "message_error") { + // Handle message error + } +} +``` + +### 2. Register the Callback + +```c +void *ctx = lmapi_create_node(config, callback, userData); +lmapi_set_event_callback(ctx, event_callback, NULL); +``` + +### 3. Start the Node + +Once the node is started, events will be delivered to your callback: + +```c +lmapi_start_node(ctx, callback, userData); +``` + +## Event Flow + +For a typical successful message send: + +1. **send** → Returns request ID +2. **message_sent** → Message accepted and queued +3. **message_propagated** → Message delivered to peers + +For a failed message send: + +1. **send** → Returns request ID +2. **message_sent** → Message accepted and queued +3. **message_error** → Delivery failed with error description + +## Important Notes + +1. **Thread Safety**: The event callback is invoked from the FFI worker thread. Ensure your callback is thread-safe if it accesses shared state. + +2. **Non-Blocking**: Keep the callback fast and non-blocking. Do not perform long-running operations in the callback. + +3. **JSON Parsing**: The example uses a simple string-based parser. For production, use a proper JSON library like: + - [cJSON](https://github.com/DaveGamble/cJSON) + - [json-c](https://github.com/json-c/json-c) + - [Jansson](https://github.com/akheron/jansson) + +4. **Memory Management**: The message buffer is owned by the library. Copy any data you need to retain. + +5. **Event Order**: Events are delivered in the order they occur, but timing depends on network conditions. + +## Example Implementation + +See `examples/liblmapi_example.c` for a complete working example that: +- Registers an event callback +- Sends a message +- Receives and prints all three event types +- Properly parses the JSON event structure + +## Debugging Events + +To see all events during development: + +```c +void debug_event_callback(int ret, const char *msg, size_t len, void *userData) { + printf("Event received: %.*s\n", (int)len, msg); +} +``` + +This will print the raw JSON for all events, helping you understand the event structure. diff --git a/liblmapi/README.md b/liblmapi/README.md new file mode 100644 index 000000000..6b9e17095 --- /dev/null +++ b/liblmapi/README.md @@ -0,0 +1,262 @@ +# Logos Messaging API (LMAPI) Library + +A C FFI library providing a simplified interface to Logos Messaging functionality. + +## Overview + +This library wraps the high-level API functions from `waku/api/api.nim` and exposes them via a C FFI interface, making them accessible from C, C++, and other languages that support C FFI. + +## API Functions + +### Node Lifecycle + +#### `lmapi_create_node` +Creates a new instance of the node from the given configuration JSON. + +```c +void *lmapi_create_node( + const char *configJson, + FFICallBack callback, + void *userData +); +``` + +**Parameters:** +- `configJson`: JSON string containing node configuration +- `callback`: Callback function to receive the result +- `userData`: User data passed to the callback + +**Returns:** Pointer to the context needed by other API functions, or NULL on error. + +**Example configuration JSON:** +```json +{ + "mode": "Core", + "clusterId": 1, + "entryNodes": [ + "enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im" + ], + "networkingConfig": { + "listenIpv4": "0.0.0.0", + "p2pTcpPort": 60000, + "discv5UdpPort": 9000 + } +} +``` + +#### `lmapi_start_node` +Starts the node. + +```c +int lmapi_start_node( + void *ctx, + FFICallBack callback, + void *userData +); +``` + +#### `lmapi_stop_node` +Stops the node. + +```c +int lmapi_stop_node( + void *ctx, + FFICallBack callback, + void *userData +); +``` + +#### `lmapi_destroy` +Destroys a node instance and frees resources. + +```c +int lmapi_destroy( + void *ctx, + FFICallBack callback, + void *userData +); +``` + +### Messaging + +#### `lmapi_subscribe` +Subscribe to a content topic to receive messages. + +```c +int lmapi_subscribe( + void *ctx, + FFICallBack callback, + void *userData, + const char *contentTopic +); +``` + +**Parameters:** +- `ctx`: Context pointer from `lmapi_create_node` +- `callback`: Callback function to receive the result +- `userData`: User data passed to the callback +- `contentTopic`: Content topic string (e.g., "/myapp/1/chat/proto") + +#### `lmapi_unsubscribe` +Unsubscribe from a content topic. + +```c +int lmapi_unsubscribe( + void *ctx, + FFICallBack callback, + void *userData, + const char *contentTopic +); +``` + +#### `lmapi_send` +Send a message. + +```c +int lmapi_send( + void *ctx, + FFICallBack callback, + void *userData, + const char *messageJson +); +``` + +**Parameters:** +- `messageJson`: JSON string containing the message + +**Example message JSON:** +```json +{ + "contentTopic": "/myapp/1/chat/proto", + "payload": "SGVsbG8gV29ybGQ=", + "ephemeral": false +} +``` + +Note: The `payload` field should be base64-encoded. + +**Returns:** Request ID in the callback message that can be used to track message delivery. + +### Events + +#### `lmapi_set_event_callback` +Sets a callback that will be invoked whenever an event occurs (e.g., message received). + +```c +void lmapi_set_event_callback( + void *ctx, + FFICallBack callback, + void *userData +); +``` + +**Important:** The callback should be fast, non-blocking, and thread-safe. + +## Building + +The library follows the same build system as the main Logos Messaging project. + +### Build the library + +```bash +make liblmapiStatic # Build static library +# or +make liblmapiDynamic # Build dynamic library +``` + +## Return Codes + +All functions that return `int` use the following return codes: + +- `RET_OK` (0): Success +- `RET_ERR` (1): Error +- `RET_MISSING_CALLBACK` (2): Missing callback function + +## Callback Function + +All API functions use the following callback signature: + +```c +typedef void (*FFICallBack)( + int callerRet, + const char *msg, + size_t len, + void *userData +); +``` + +**Parameters:** +- `callerRet`: Return code (RET_OK, RET_ERR, etc.) +- `msg`: Response message (may be empty for success) +- `len`: Length of the message +- `userData`: User data passed in the original call + +## Example Usage + +```c +#include "liblmapi.h" +#include + +void callback(int ret, const char *msg, size_t len, void *userData) { + if (ret == RET_OK) { + printf("Success: %.*s\n", (int)len, msg); + } else { + printf("Error: %.*s\n", (int)len, msg); + } +} + +int main() { + const char *config = "{" + "\"mode\": \"Core\"," + "\"clusterId\": 1" + "}"; + + // Create node + void *ctx = lmapi_create_node(config, callback, NULL); + if (ctx == NULL) { + return 1; + } + + // Start node + lmapi_start_node(ctx, callback, NULL); + + // Subscribe to a topic + lmapi_subscribe(ctx, callback, NULL, "/myapp/1/chat/proto"); + + // Send a message + const char *msg = "{" + "\"contentTopic\": \"/myapp/1/chat/proto\"," + "\"payload\": \"SGVsbG8gV29ybGQ=\"," + "\"ephemeral\": false" + "}"; + lmapi_send(ctx, callback, NULL, msg); + + // Clean up + lmapi_stop_node(ctx, callback, NULL); + lmapi_destroy(ctx, callback, NULL); + + return 0; +} +``` + +## Architecture + +The library is structured as follows: + +- `liblmapi.h`: C header file with function declarations +- `liblmapi.nim`: Main library entry point +- `declare_lib.nim`: Library declaration and initialization +- `lmapi/node_api.nim`: Node lifecycle API implementation +- `lmapi/messaging_api.nim`: Subscribe/send API implementation + +The library uses the nim-ffi framework for FFI infrastructure, which handles: +- Thread-safe request processing +- Async operation management +- Memory management between C and Nim +- Callback marshaling + +## See Also + +- Main API documentation: `waku/api/api.nim` +- Original libwaku library: `library/libwaku.nim` +- nim-ffi framework: `vendor/nim-ffi/` diff --git a/liblmapi/examples/README.md b/liblmapi/examples/README.md new file mode 100644 index 000000000..37c947e26 --- /dev/null +++ b/liblmapi/examples/README.md @@ -0,0 +1,88 @@ +# Examples for liblmapi + +This directory contains example programs demonstrating the usage of the Logos Messaging API (LMAPI) library. + +## Building the Examples + +### Prerequisites + +1. Build the liblmapi library first: + ```bash + cd /path/to/logos-messaging-nim + make liblmapi + ``` + +2. The library will be available in `build/liblmapi.so` (or `.dylib` on macOS, `.dll` on Windows) + +### Compile the liblmapi Example + +#### On Linux/macOS: +```bash +# Shared library +gcc -o liblmapi_example liblmapi_example.c -I.. -L../../build -llmapi -Wl,-rpath,../../build + +# Static library (if built with STATIC=1) +gcc -o liblmapi_example liblmapi_example.c -I.. ../../build/liblmapi.a -lpthread -lm -ldl +``` + +#### On macOS: +```bash +gcc -o liblmapi_example liblmapi_example.c -I.. -L../../build -llmapi +``` + +#### On Windows (MinGW): +```bash +gcc -o liblmapi_example.exe liblmapi_example.c -I.. -L../../build -llmapi -lws2_32 +``` + +## Running the Examples + +### liblmapi Example + +```bash +./liblmapi_example +``` + +This example demonstrates: +1. Creating a node with configuration +2. Starting the node +3. Subscribing to a content topic +4. Sending a message +5. Unsubscribing from the topic +6. Stopping and destroying the node + +### Expected Output + +``` +=== Logos Messaging API (LMAPI) Example === + +1. Creating node... +[create_node] Success + +2. Starting node... +[start_node] Success + +3. Subscribing to content topic... +[subscribe] Success + +4. Sending a message... +[send] Success: + +5. Unsubscribing from content topic... +[unsubscribe] Success + +6. Stopping node... +[stop_node] Success + +7. Destroying context... +[destroy] Success + +=== Example completed === +``` + +## Notes + +- The examples use simple synchronous callbacks with sleep() for demonstration +- In production code, you should use proper async patterns +- Error handling in these examples is basic - production code should be more robust +- The payload in messages must be base64-encoded diff --git a/liblmapi/examples/simple_example.c b/liblmapi/examples/liblmapi_example.c similarity index 94% rename from liblmapi/examples/simple_example.c rename to liblmapi/examples/liblmapi_example.c index 654c009ef..dc6fd8766 100644 --- a/liblmapi/examples/simple_example.c +++ b/liblmapi/examples/liblmapi_example.c @@ -9,26 +9,26 @@ const char* extract_json_field(const char *json, const char *field, char *buffer, size_t bufSize) { char searchStr[256]; snprintf(searchStr, sizeof(searchStr), "\"%s\":\"", field); - + const char *start = strstr(json, searchStr); if (!start) { return NULL; } - + start += strlen(searchStr); const char *end = strchr(start, '"'); if (!end) { return NULL; } - + size_t len = end - start; if (len >= bufSize) { len = bufSize - 1; } - + memcpy(buffer, start, len); buffer[len] = '\0'; - + return buffer; } @@ -37,7 +37,7 @@ void event_callback(int ret, const char *msg, size_t len, void *userData) { if (ret != RET_OK || msg == NULL || len == 0) { return; } - + // Create null-terminated string for easier parsing char *eventJson = malloc(len + 1); if (!eventJson) { @@ -45,14 +45,14 @@ void event_callback(int ret, const char *msg, size_t len, void *userData) { } memcpy(eventJson, msg, len); eventJson[len] = '\0'; - + // Extract eventType char eventType[64]; if (!extract_json_field(eventJson, "eventType", eventType, sizeof(eventType))) { free(eventJson); return; } - + // Handle different event types if (strcmp(eventType, "message_sent") == 0) { char requestId[128]; @@ -60,7 +60,7 @@ void event_callback(int ret, const char *msg, size_t len, void *userData) { extract_json_field(eventJson, "requestId", requestId, sizeof(requestId)); extract_json_field(eventJson, "messageHash", messageHash, sizeof(messageHash)); printf("📤 [EVENT] Message sent - RequestID: %s, Hash: %s\n", requestId, messageHash); - + } else if (strcmp(eventType, "message_error") == 0) { char requestId[128]; char messageHash[128]; @@ -68,20 +68,20 @@ void event_callback(int ret, const char *msg, size_t len, void *userData) { extract_json_field(eventJson, "requestId", requestId, sizeof(requestId)); extract_json_field(eventJson, "messageHash", messageHash, sizeof(messageHash)); extract_json_field(eventJson, "error", error, sizeof(error)); - printf("❌ [EVENT] Message error - RequestID: %s, Hash: %s, Error: %s\n", + printf("❌ [EVENT] Message error - RequestID: %s, Hash: %s, Error: %s\n", requestId, messageHash, error); - + } else if (strcmp(eventType, "message_propagated") == 0) { char requestId[128]; char messageHash[128]; extract_json_field(eventJson, "requestId", requestId, sizeof(requestId)); extract_json_field(eventJson, "messageHash", messageHash, sizeof(messageHash)); printf("✅ [EVENT] Message propagated - RequestID: %s, Hash: %s\n", requestId, messageHash); - + } else { printf("ℹ️ [EVENT] Unknown event type: %s\n", eventType); } - + free(eventJson); } @@ -105,8 +105,10 @@ int main() { // Configuration JSON for creating a node const char *config = "{" "\"mode\": \"Core\"," - "\"clusterId\": 1," - "\"entryNodes\": []," + "\"clusterId\": 16," + "\"numShards\": 5," + "\"shards\": [64, 128, 1, 32, 256]," + "\"entryNodes\": [\"/dns4/boot-01.gc-us-central1-a.status.prod.status.im/tcp/30303/p2p/16Uiu2HAm8mUZ18tBWPXDQsaF7PbCKYA35z7WB2xNZH2EVq1qS8LJ\"]," "\"networkingConfig\": {" "\"listenIpv4\": \"0.0.0.0\"," "\"p2pTcpPort\": 60000," @@ -153,7 +155,7 @@ int main() { // Wait for message events to arrive printf("Waiting for message delivery events...\n"); - sleep(3); + sleep(60); printf("\n6. Unsubscribing from content topic...\n"); lmapi_unsubscribe(ctx, simple_callback, (void *)"unsubscribe", contentTopic);