Outgoing/Incoming Message Handling

Overview

Outgoing messages

Our Software Development Kit (SDK) communicates with the Fireblocks REST API through a customizable callback function that is set during SDK initialization. The callback is responsible for handling outgoing requests, such as MPC messages related to key generation, transaction signing, or backup and recovery operations.

A simple implementation of the callback would be to proxy all requests to the customer's backend, which would then forward them to the Fireblocks API RPC endpoint using the appropriate API user that was already created.

The outgoing message handler should implement the following method (according to the defined interface):

  • handleOutgoingMessage(payload: string): the method being called by the Fireblocks Non-Custodial Wallet (NCW) SDK with the message that should be sent to the backend and then to the Fireblocks RPC.

Examples

const messagesHandler: IMessagesHandler = {
          handleOutgoingMessage: (message: string) => {
            if (!apiService) {
              throw new Error("apiService is not initialized");
            }
            // Send the message to the backend server
            return apiService.sendMessage(deviceId, message);
          },
        };
// create your own implementation of the FireblocksMessageHandler and pass it in the Fireblocks.initialize method
val fireblocksMessageHandler = FireblocksMessageHandlerImpl()

// An implementation example for the FireblocksMessageHandler. 
// Override the handleOutgoingMessage method and call pass the payload to Fireblocks BE using your BE implementation. 
// Make sure you to invoke the responseCallback with the response body or the errorCallback in case of an error
class FireblocksMessageHandlerImpl(
private val context: Context, 
private val deviceId: String) 
: FireblocksMessageHandler, CoroutineScope {
    private val job = Job()
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.IO + job

    override fun handleOutgoingMessage(
payload:String,
responseCallback: (responseBody: String?) -> Unit,
      errorCallback: (errorMessage: String?) -> Unit) {
        runBlocking {
            withContext(Dispatchers.IO) {
                // do rest API call
                Timber.i("calling invoke rest API")
                runCatching {
                    val response = Api.with(StorageManager.get(context, deviceId)).invoke(deviceId, MessageBody(payload)).execute()
                    Timber.i("got response from invoke rest API, code:${response.code()}, isSuccessful:${response.isSuccessful}")
                    responseCallback(response.body())
                }.onFailure {
                    Timber.e(it, "Failed to call invoke Api")
                    errorCallback("Failed to call invoke Api")
                }
            }
        }
    }
}

extension DeviceInstance: MessageHandlerDelegate {
    func handleOutgoingMessage(payload: String, response: @escaping (String?) -> (), error: @escaping (String?) -> ()) {
        sessionManager.rpc(deviceId: deviceId, message: payload) { response in
            //handle response
        } error: { error in
            //handle error
        }
    }
}

Incoming messages

🚧

Prerequisites

Make sure you have completed the Webhook Configuration guide before continuing.

After setting up your webhook, you'll begin to receive push notifications covering various message types, including transaction status updates and multiple devices webhook notifications