Sign messages
Prerequisites
Before implementing message signing:
- Ensure Openfort's
embeddedState
isready
- Verify the user is properly authenticated
- Have an embedded wallet configured
Methods
SignMessage
Signs a plain text message using the EIP-191 personal_sign standard.
Method Signature:public async UniTask<string> SignMessage(SignMessageRequest request)
SignMessageRequest request
- The message signing request containing the message to sign
UniTask<string>
- The signature as a hex string
public class SignMessageRequest
{
public string Message { get; set; }
public SignMessageRequest(string message)
{
Message = message;
}
}
using System;
using UnityEngine;
using Cysharp.Threading.Tasks;
using Openfort.OpenfortSDK;
using Openfort.OpenfortSDK.Model;
public class BasicMessageSigner : MonoBehaviour
{
private OpenfortSDK openfort;
private async void Start()
{
// Initialize SDK
openfort = await OpenfortSDK.Init(
"YOUR_OPENFORT_PUBLISHABLE_KEY",
"YOUR_SHIELD_PUBLISHABLE_KEY"
);
}
public async UniTask<string> SignTextMessage(string message)
{
try
{
// Check if wallet is ready
var state = await openfort.GetEmbeddedState();
if (state != EmbeddedState.READY)
{
throw new InvalidOperationException(quot;Wallet not ready. State: {state}");
}
// Create request and sign
var request = new SignMessageRequest(message);
var signature = await openfort.SignMessage(request);
Debug.Log(quot;Message '{message}' signed successfully");
Debug.Log(quot;Signature: {signature}");
return signature;
}
catch (Exception e)
{
Debug.LogError(quot;Failed to sign message: {e.Message}");
throw;
}
}
// Example usage
public async UniTaskVoid SignWelcomeMessage()
{
string welcomeMsg = "Welcome to My Game!";
await SignTextMessage(welcomeMsg);
}
}
SignTypedData
Signs structured data using the EIP-712 eth_signTypedData_v4 standard.
Method Signature:public async UniTask<string> SignTypedData(SignTypedDataRequest request)
SignTypedDataRequest request
- The typed data signing request
UniTask<string>
- The signature as a hex string
public class SignTypedDataRequest
{
public Dictionary<string, object> Domain { get; set; }
public Dictionary<string, object[]> Types { get; set; }
public Dictionary<string, object> Value { get; set; }
public SignTypedDataRequest(
Dictionary<string, object> domain,
Dictionary<string, object[]> types,
Dictionary<string, object> value)
{
Domain = domain;
Types = types;
Value = value;
}
}
using System;
using System.Collections.Generic;
using UnityEngine;
using Cysharp.Threading.Tasks;
using Openfort.OpenfortSDK;
using Openfort.OpenfortSDK.Model;
public class TypedDataSigner : MonoBehaviour
{
private OpenfortSDK openfort;
private async void Start()
{
openfort = await OpenfortSDK.Init(
"YOUR_OPENFORT_PUBLISHABLE_KEY",
"YOUR_SHIELD_PUBLISHABLE_KEY"
);
}
public async UniTask<string> SignPlayerScore(string playerName, int score, string contractAddress)
{
try
{
// Check wallet state
var state = await openfort.GetEmbeddedState();
if (state != EmbeddedState.READY)
{
throw new InvalidOperationException(quot;Wallet not ready. State: {state}");
}
// Define the domain
var domain = new Dictionary<string, object>
{
{ "name", "GameLeaderboard" },
{ "version", "1" },
{ "chainId", 80002 },
{ "verifyingContract", contractAddress }
};
// Define the types
var types = new Dictionary<string, object[]>
{
{
"ScoreEntry", new object[]
{
new Dictionary<string, object> { { "name", "player" }, { "type", "string" } },
new Dictionary<string, object> { { "name", "score" }, { "type", "uint256" } },
new Dictionary<string, object> { { "name", "timestamp" }, { "type", "uint256" } }
}
}
};
// Define the value
var value = new Dictionary<string, object>
{
{ "player", playerName },
{ "score", score },
{ "timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
};
// Create request and sign
var request = new SignTypedDataRequest(domain, types, value);
var signature = await openfort.SignTypedData(request);
Debug.Log(quot;Score entry signed for {playerName}: {score}");
return signature;
}
catch (Exception e)
{
Debug.LogError(quot;Failed to sign typed data: {e.Message}");
throw;
}
}
}
Complete Example
Here's a comprehensive example combining both message types:
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Cysharp.Threading.Tasks;
using Openfort.OpenfortSDK;
using Openfort.OpenfortSDK.Model;
public class MessageSigningDemo : MonoBehaviour
{
private OpenfortSDK openfort;
[Header("UI References")]
[SerializeField] private Button signMessageButton;
[SerializeField] private Button signTypedDataButton;
[SerializeField] private TMPro.TMP_InputField messageInput;
[SerializeField] private TMPro.TextMeshProUGUI signatureOutput;
private async void Start()
{
// Initialize SDK
openfort = await OpenfortSDK.Init(
"YOUR_OPENFORT_PUBLISHABLE_KEY",
"YOUR_SHIELD_PUBLISHABLE_KEY"
);
// Setup UI
signMessageButton.onClick.AddListener(() => SignUserMessage().Forget());
signTypedDataButton.onClick.AddListener(() => SignGameData().Forget());
}
private async UniTaskVoid SignUserMessage()
{
try
{
await WaitForWalletReady();
string message = messageInput.text;
if (string.IsNullOrEmpty(message))
message = "Hello from Unity!";
var request = new SignMessageRequest(message);
var signature = await openfort.SignMessage(request);
signatureOutput.text = quot;Signature: {signature.Substring(0, 20)}...";
}
catch (Exception e)
{
signatureOutput.text = quot;Error: {e.Message}";
}
}
private async UniTaskVoid SignGameData()
{
try
{
await WaitForWalletReady();
// Example game data
var domain = new Dictionary<string, object>
{
{ "name", "Unity Game" },
{ "version", "1" },
{ "chainId", 80002 }
};
var types = new Dictionary<string, object[]>
{
{
"GameData", new object[]
{
new Dictionary<string, object> { { "name", "level" }, { "type", "uint256" } },
new Dictionary<string, object> { { "name", "player" }, { "type", "string" } }
}
}
};
var value = new Dictionary<string, object>
{
{ "level", 5 },
{ "player", "TestPlayer" }
};
var request = new SignTypedDataRequest(domain, types, value);
var signature = await openfort.SignTypedData(request);
signatureOutput.text = quot;Typed signature: {signature.Substring(0, 20)}...";
}
catch (Exception e)
{
signatureOutput.text = quot;Error: {e.Message}";
}
}
private async UniTask WaitForWalletReady()
{
while (true)
{
var state = await openfort.GetEmbeddedState();
if (state == EmbeddedState.READY) return;
await UniTask.Delay(100);
}
}
}
Examples
Unity Sample Android Embedded Wallet
An integration with Google Play Games using Firebase Auth as a third party auth provider to create a non-custodial embedded wallet.
Unity Sample WebGL Embedded Wallet
An integration with Openfort Auth with non-custodial embedded wallet.