Skip to content

Using Smart Wallets

To use smart wallets, you could use the EIP1193 provider or use a backend. This guide teaches how to make different requests to the smart wallet with the backend and Unity (it's easier to do so in the context of gaming because no need to encode transactions with Unity).

Sign message

To sign message with the smart wallet simply call the Openfort's signMessage or signTypedData method like so:

SignMessageRequest signMessageRequest = new SignMessageRequest("Hello World!");
string signature = await openfort.embeddedWallet.signMessage(signMessageRequest);

Transactions

1. Create a transaction- Server side

Create a request to your backend to create a transaction. In the body of the request:

  • Include the player that signs the transaction.
  • Include the policy that interacts with the contract for gas. If non-existent the user will need to have gas tokens.
  • Include optimistic if you want the transactions to be confirmed faster.

Depending on the type of transaction you're creating you'll define interactions. The interactions field is an array of objects that contain the information of the contract to interact with, the function to call, and the arguments to pass to the function.

  • the interactions field contains the contract that has previously been added to Openfort.
  • the functionName defines the function to call from within the contract.
  • If there exist more than one function with the same name, the functionArgs will be used to determine which function to call.
curl
curl https://api.openfort.io/v1/transaction_intents \
  -H "Authorization: Bearer $YOUR_SECRET_KEY" \
  -d player="pla_..." \
  -d policy="pol_..." \
  -d chainId=80002 \
  -d optimistic=true \
  -d "interactions[0][contract]"="con_..." \
  -d "interactions[0][functionName]"="mint" \
  -d "interactions[0][functionArgs][0]"="0x63B7...484f"

Native

Send the value of native tokens in the smallest denomination of the native currency i.e. wei (10^18) and as a string.

curl
curl https://api.openfort.io/v1/transaction_intents \
  -H "Authorization: Bearer $YOUR_SECRET_KEY" \
  -d player="pla_..." \
  -d policy="pol_..." \
  -d chainId=80002 \
  -d optimistic=true \
  -d "interactions[0][value]=1000" \
  -d "interactions[0][to]=pla_..."

For a useful resource for computing the Wei, you can visit the wei calculator.

Batch

Smart accounts support batching transactions, allowing multiple actions to be rolled into one. This feature significantly simplifies Web3 interactions for your users. For example, instead of executing approve() and then transfer(), your user can perform both in a single transaction.

Batching transactions offers several key benefits:

  • Users only wait for one transaction to complete instead of multiple.
  • Users save on gas fees.
  • If any transaction in the batch fails, the entire batch reverts, preventing users from ending up in an inconsistent state. This characteristic is known as "atomicity."

Fore security reasons, there is a limit of 9 interactions per transaction intent.

In the case that, in your contract, you have multiple functions with the same functionName and number of arguments, you can also include the functionName together with the argument types e.g. mint(address)

curl
curl https://api.openfort.io/v1/transaction_intents \
  -H "Authorization: Bearer $YOUR_SECRET_KEY" \
  -d player="pla_...", \
  -d policy="pol_..." \
  -d chainId=80002 \
  -d optimistic=true \
  -d "interactions[0][contract]=con_..." \
  -d "interactions[0][functionName]=mint" \
  -d "interactions[0][functionArgs][0]=0x63B7...484f" \
  -d "interactions[1][contract]=con_..." \
  -d "interactions[1][functionName]=transfer" \
  -d "interactions[1][functionArgs][0]=0x32B7...213d"

2. Sign the transaction. - Client side

Use the nextAction returned by the backend to sign the transaction with the embedded wallet.

The transaction will be automatically signed and broadcasted by using the sendSignatureTransactionIntentRequest method.

private async void Mint() {
  // your backend that creates a mint request
  var webRequest = UnityWebRequest.Post("https://your-backend.com/api/mint", "");
  webRequest.SetRequestHeader("Authorization", "Bearer " + AccessToken);
  webRequest.SetRequestHeader("Content-Type", "application/json");
  webRequest.SetRequestHeader("Accept", "application/json");
  await SendWebRequestAsync(webRequest);
 
  Debug.Log("Mint request sent");
  if (webRequest.result != UnityWebRequest.Result.Success) {
    Debug.Log("Mint Failed: " + webRequest.error);
    return;
  }
 
  var responseText = webRequest.downloadHandler.text;
  Debug.Log("Mint Response: " + responseText);
  var responseJson = JsonConvert.DeserializeObject < RootObject > (responseText);
  var id = responseJson.Data.Id;
  if (responseJson.Data.NextAction == null) {
    Debug.Log("No Next Action");
    return;
  }
 
  var nextAction = responseJson.Data.NextAction.Payload.UserOpHash;
 
  Debug.Log("Next Action: " + nextAction);
  // This example assumes you have already checked that Openfort 'embeddedState' is 
  // `ready` and the user is `authenticated`
  var intentResponse = await Openfort.SendSignatureTransactionIntentRequest(id, nextAction);
  Debug.Log("Intent Response: " + intentResponse);
}
 
private Task SendWebRequestAsync(UnityWebRequest webRequest) {
  TaskCompletionSource < bool > tcs = new TaskCompletionSource < bool > ();
  webRequest.SendWebRequest().completed += _ => {
    switch (webRequest.result) {
    case UnityWebRequest.Result.Success:
      tcs.SetResult(true);
      break;
    default:
      tcs.SetException(new Exception(webRequest.error));
      break;
    }
  };
  return tcs.Task;
}

Examples

Unity Sample Android

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

An integration with Openfort Auth with non-custodial embedded wallet.