Skip to content

Commit

Permalink
Thirdweb Engine Relayer Integration
Browse files Browse the repository at this point in the history
Replaces OZ Defender
  • Loading branch information
0xFirekeeper committed Apr 16, 2024
1 parent bf98f94 commit 4eda906
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 105 deletions.
19 changes: 8 additions & 11 deletions Assets/Thirdweb/Core/Scripts/ThirdwebManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ public class ThirdwebManager : MonoBehaviour
[Tooltip("IPFS Gateway Override")]
public string storageIpfsGatewayUrl = null;

[Tooltip("Autotask URL")]
[Tooltip("Find out more about relayers here https://portal.thirdweb.com/engine/features/relayers")]
public string relayerUrl = null;

[Tooltip("Forwarders can be found here https://github.com/thirdweb-dev/ozdefender-autotask")]
[Tooltip("Forwarder Contract Address (Defaults to 0xD04F98C88cE1054c90022EE34d566B9237a1203C if left empty)")]
public string forwarderAddress = null;

[Tooltip("Forwarder Domain Override (Defaults to GSNv2 Forwarder if left empty)")]
Expand Down Expand Up @@ -206,17 +206,14 @@ public void Initialize(string chainIdentifier)
{
options.storage = new ThirdwebSDK.StorageOptions() { ipfsGatewayUrl = storageIpfsGatewayUrl };
}
if (!string.IsNullOrEmpty(relayerUrl) && !string.IsNullOrEmpty(forwarderAddress))
if (!string.IsNullOrEmpty(relayerUrl))
{
options.gasless = new ThirdwebSDK.GaslessOptions()
options.relayer = new ThirdwebSDK.RelayerOptions()
{
openzeppelin = new ThirdwebSDK.OZDefenderOptions()
{
relayerUrl = this.relayerUrl,
relayerForwarderAddress = this.forwarderAddress,
domainName = string.IsNullOrEmpty(this.forwarderDomainOverride) ? "GSNv2 Forwarder" : this.forwarderDomainOverride,
domainVersion = string.IsNullOrEmpty(this.forwaderVersionOverride) ? "0.0.1" : this.forwaderVersionOverride
}
relayerUrl = this.relayerUrl,
forwarderAddress = string.IsNullOrEmpty(this.forwarderAddress) ? "0xD04F98C88cE1054c90022EE34d566B9237a1203C" : this.forwarderAddress,
domainName = string.IsNullOrEmpty(this.forwarderDomainOverride) ? "GSNv2 Forwarder" : this.forwarderDomainOverride,
domainVersion = string.IsNullOrEmpty(this.forwaderVersionOverride) ? "0.0.1" : this.forwaderVersionOverride
};
}

Expand Down
50 changes: 5 additions & 45 deletions Assets/Thirdweb/Core/Scripts/ThirdwebSDK.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ public class ThirdwebSDK
public struct Options
{
/// <summary>
/// Gasless configuration options for the Thirdweb SDK.
/// Gasless relayer configuration options for Thirdweb Engine..
/// </summary>
public GaslessOptions? gasless;
public RelayerOptions? relayer;

/// <summary>
/// Storage configuration options for the Thirdweb SDK.
Expand Down Expand Up @@ -204,33 +204,10 @@ public struct StorageOptions
}

/// <summary>
/// Gasless configuration options.
/// Thirdweb Engine Relayer configuration options.
/// </summary>
[System.Serializable]
public struct GaslessOptions
{
/// <summary>
/// OpenZeppelin Defender Gasless configuration options.
/// </summary>
public OZDefenderOptions? openzeppelin;

/// <summary>
/// [Obsolete] Biconomy Gasless configuration options. Biconomy is not fully supported and will be removed soon. Use OpenZeppelin Defender instead.
/// </summary>
[System.Obsolete("Biconomy is not fully supported and will be removed soon. Use OpenZeppelin Defender instead.")]
public BiconomyOptions? biconomy;

/// <summary>
/// Indicates whether experimental chainless support is enabled.
/// </summary>
public bool experimentalChainlessSupport;
}

/// <summary>
/// OpenZeppelin Defender Gasless configuration options.
/// </summary>
[System.Serializable]
public struct OZDefenderOptions
public struct RelayerOptions
{
/// <summary>
/// The URL of the relayer service.
Expand All @@ -240,7 +217,7 @@ public struct OZDefenderOptions
/// <summary>
/// The address of the relayer forwarder.
/// </summary>
public string relayerForwarderAddress;
public string forwarderAddress;

/// <summary>
/// The domain name for the forwarder.
Expand All @@ -253,23 +230,6 @@ public struct OZDefenderOptions
public string domainVersion;
}

/// <summary>
/// Biconomy Gasless configuration options.
/// </summary>
[System.Serializable]
public struct BiconomyOptions
{
/// <summary>
/// The API ID for Biconomy.
/// </summary>
public string apiId;

/// <summary>
/// The API key for Biconomy.
/// </summary>
public string apiKey;
}

private readonly string chainOrRPC;

/// <summary>
Expand Down
93 changes: 46 additions & 47 deletions Assets/Thirdweb/Core/Scripts/Transaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Nethereum.Contracts;
using Nethereum.ABI.FunctionEncoding;
using System;
using Newtonsoft.Json.Linq;

#pragma warning disable CS0618

Expand Down Expand Up @@ -341,9 +342,9 @@ public async Task<string> Send(bool? gasless = null)
await EstimateAndSetGasLimitAsync();
if (Input.Value == null)
Input.Value = new HexBigInteger(0);
bool isGaslessSetup = ThirdwebManager.Instance.SDK.Session.Options.gasless.HasValue && ThirdwebManager.Instance.SDK.Session.Options.gasless.Value.openzeppelin.HasValue;
bool isGaslessSetup = ThirdwebManager.Instance.SDK.Session.Options.relayer.HasValue && !string.IsNullOrEmpty(ThirdwebManager.Instance.SDK.Session.Options.relayer.Value.relayerUrl);
if (gasless != null && gasless.Value && !isGaslessSetup)
throw new UnityException("Gasless transactions are not enabled. Please enable them in the SDK options.");
throw new UnityException("Gasless relayer transactions are not enabled. Please enable them in the SDK options.");
bool sendGaslessly = gasless == null ? isGaslessSetup : gasless.Value;
if (sendGaslessly)
return await SendGasless();
Expand Down Expand Up @@ -484,10 +485,10 @@ private async Task<string> SendGasless()
}
else
{
string relayerUrl = ThirdwebManager.Instance.SDK.Session.Options.gasless.Value.openzeppelin?.relayerUrl;
string forwarderAddress = ThirdwebManager.Instance.SDK.Session.Options.gasless.Value.openzeppelin?.relayerForwarderAddress;
string forwarderDomain = ThirdwebManager.Instance.SDK.Session.Options.gasless.Value.openzeppelin?.domainName;
string forwarderVersion = ThirdwebManager.Instance.SDK.Session.Options.gasless.Value.openzeppelin?.domainVersion;
string relayerUrl = ThirdwebManager.Instance.SDK.Session.Options.relayer?.relayerUrl ?? throw new UnityException("Relayer URL not set in SDK options.");
string forwarderAddress = ThirdwebManager.Instance.SDK.Session.Options.relayer?.forwarderAddress ?? "0xD04F98C88cE1054c90022EE34d566B9237a1203C";
string forwarderDomain = ThirdwebManager.Instance.SDK.Session.Options.relayer?.domainName ?? "GSNv2 Forwarder";
string forwarderVersion = ThirdwebManager.Instance.SDK.Session.Options.relayer?.domainVersion ?? "0.0.1";

Input.Nonce = (
await TransactionManager.ThirdwebRead<MinimalForwarder.GetNonceFunction, MinimalForwarder.GetNonceOutputDTO>(
Expand All @@ -506,6 +507,8 @@ private async Task<string> SendGasless()
Data = Input.Data
};

ThirdwebDebug.Log($"Forwarding request: {JsonConvert.SerializeObject(request)}");

var signature = await EIP712.GenerateSignature_MinimalForwarder(
forwarderDomain,
forwarderVersion,
Expand All @@ -514,7 +517,13 @@ private async Task<string> SendGasless()
request
);

var postData = new RelayerRequest(request, signature, forwarderAddress);
var postData = new RelayerRequest()
{
Type = "forward",
Request = request,
Signature = signature,
ForwarderAddress = forwarderAddress,
};

using UnityWebRequest req = UnityWebRequest.Post(relayerUrl, "");
byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(postData));
Expand All @@ -530,17 +539,32 @@ private async Task<string> SendGasless()
}
else
{
var response = JsonConvert.DeserializeObject<RelayerResponse>(req.downloadHandler.text);
if (response.status != "success")
{
throw new UnityException(
$"Forward Request Failed!\nError: {req.downloadHandler.text}\nRelayer URL: {relayerUrl}\nRelayer Forwarder Address: {forwarderAddress}\nRequest: {request}\nSignature: {signature}\nPost Data: {postData}"
);
}
var result = JsonConvert.DeserializeObject<RelayerResult>(response.result);
return result.txHash;
var queueId = JsonConvert.DeserializeObject<JObject>(req.downloadHandler.text)["result"]["queueId"].ToString();
ThirdwebDebug.Log($"Forwarded request to relayer with queue ID: {queueId}");
return await FetchTxHashFromQueueId(new Uri(relayerUrl).GetLeftPart(UriPartial.Authority), queueId);
}
}
}

private async Task<string> FetchTxHashFromQueueId(string engineUrl, string queueId)
{
string txHash = null;
while (string.IsNullOrEmpty(txHash) && Application.isPlaying)
{
using UnityWebRequest req = UnityWebRequest.Get($"{engineUrl}/transaction/status/{queueId}");
await new WaitForSeconds(1f);
await req.SendWebRequest();
if (req.result != UnityWebRequest.Result.Success)
{
throw new UnityException($"Failed to fetch transaction hash from queue ID {queueId}.\nError: {req.downloadHandler.text}");
}
else
{
txHash = JsonConvert.DeserializeObject<JObject>(req.downloadHandler.text)["result"]["transactionHash"].ToString();
}
}
ThirdwebDebug.Log($"Transaction hash fetched from queue ID {queueId}: {txHash}");
return txHash;
}

private string GetTxBuilderRoute(string action)
Expand All @@ -550,44 +574,19 @@ private string GetTxBuilderRoute(string action)
}
}

[System.Serializable]
public struct RelayerResponse
{
[JsonProperty("status")]
public string status;

[JsonProperty("result")]
public string result;
}

[System.Serializable]
public struct RelayerResult
{
[JsonProperty("txHash")]
public string txHash;
}

[System.Serializable]
public struct RelayerRequest
{
[JsonProperty("type")]
public string Type;

[JsonProperty("request")]
public MinimalForwarder.ForwardRequest request;
public MinimalForwarder.ForwardRequest Request;

[JsonProperty("signature")]
public string signature;
public string Signature;

[JsonProperty("forwarderAddress")]
public string forwarderAddress;

[JsonProperty("type")]
public string type;

public RelayerRequest(MinimalForwarder.ForwardRequest request, string signature, string forwarderAddress)
{
this.request = request;
this.signature = signature;
this.forwarderAddress = forwarderAddress;
this.type = "forward";
}
public string ForwarderAddress;
}
}
4 changes: 2 additions & 2 deletions Assets/Thirdweb/Editor/ThirdwebManagerEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,12 @@ public override void OnInspectorGUI()

// OZ Defender Options
sectionExpanded[3] = DrawSectionWithExpand(
"OpenZeppelin Defender Options",
"Gasless Relayer Options",
sectionExpanded[3],
() =>
{
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.PropertyField(relayerUrlProperty);
EditorGUILayout.PropertyField(forwarderAddressProperty);

EditorGUI.BeginChangeCheck();
showGaslessOptionalFields = EditorGUILayout.ToggleLeft("Show Optional Fields", showGaslessOptionalFields);
Expand All @@ -280,6 +279,7 @@ public override void OnInspectorGUI()

if (showGaslessOptionalFields)
{
EditorGUILayout.PropertyField(forwarderAddressProperty);
EditorGUILayout.PropertyField(forwarderDomainOverrideProperty);
EditorGUILayout.PropertyField(forwaderVersionOverrideProperty);
}
Expand Down

0 comments on commit 4eda906

Please sign in to comment.