Skip to content

Commit d27f53b

Browse files
authored
[WebGL] Support Transaction.Wait and add Blocks static functions (#131)
1 parent 954fddf commit d27f53b

File tree

10 files changed

+41625
-40328
lines changed

10 files changed

+41625
-40328
lines changed

Assets/Thirdweb/Core/Plugin/thirdweb.jslib

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,98 @@ var plugin = {
252252
dynCall_viii(cb, idPtr, null, buffer);
253253
});
254254
},
255+
ThirdwebWaitForTransactionResult: async function (taskId, txHash, cb) {
256+
// convert taskId from pointer to str and allocate it to keep in memory
257+
var id = UTF8ToString(taskId);
258+
var idSize = lengthBytesUTF8(id) + 1;
259+
var idPtr = _malloc(idSize);
260+
stringToUTF8(id, idPtr, idSize);
261+
// execute bridge call
262+
window.bridge
263+
.waitForTransactionResult(UTF8ToString(txHash))
264+
.then((returnStr) => {
265+
var bufferSize = lengthBytesUTF8(returnStr) + 1;
266+
var buffer = _malloc(bufferSize);
267+
stringToUTF8(returnStr, buffer, bufferSize);
268+
dynCall_viii(cb, idPtr, buffer, null);
269+
})
270+
.catch((err) => {
271+
var msg = err.message;
272+
var bufferSize = lengthBytesUTF8(msg) + 1;
273+
var buffer = _malloc(bufferSize);
274+
stringToUTF8(msg, buffer, bufferSize);
275+
dynCall_viii(cb, idPtr, null, buffer);
276+
});
277+
},
278+
ThirdwebGetLatestBlockNumber: async function (taskId, cb) {
279+
// convert taskId from pointer to str and allocate it to keep in memory
280+
var id = UTF8ToString(taskId);
281+
var idSize = lengthBytesUTF8(id) + 1;
282+
var idPtr = _malloc(idSize);
283+
stringToUTF8(id, idPtr, idSize);
284+
// execute bridge call
285+
window.bridge
286+
.getLatestBlockNumber()
287+
.then((returnStr) => {
288+
var bufferSize = lengthBytesUTF8(returnStr) + 1;
289+
var buffer = _malloc(bufferSize);
290+
stringToUTF8(returnStr, buffer, bufferSize);
291+
dynCall_viii(cb, idPtr, buffer, null);
292+
})
293+
.catch((err) => {
294+
var msg = err.message;
295+
var bufferSize = lengthBytesUTF8(msg) + 1;
296+
var buffer = _malloc(bufferSize);
297+
stringToUTF8(msg, buffer, bufferSize);
298+
dynCall_viii(cb, idPtr, null, buffer);
299+
});
300+
},
301+
ThirdwebGetBlock: async function (taskId, blockNumber, cb) {
302+
// convert taskId from pointer to str and allocate it to keep in memory
303+
var id = UTF8ToString(taskId);
304+
var idSize = lengthBytesUTF8(id) + 1;
305+
var idPtr = _malloc(idSize);
306+
stringToUTF8(id, idPtr, idSize);
307+
// execute bridge call
308+
window.bridge
309+
.getBlock(UTF8ToString(blockNumber))
310+
.then((returnStr) => {
311+
var bufferSize = lengthBytesUTF8(returnStr) + 1;
312+
var buffer = _malloc(bufferSize);
313+
stringToUTF8(returnStr, buffer, bufferSize);
314+
dynCall_viii(cb, idPtr, buffer, null);
315+
})
316+
.catch((err) => {
317+
var msg = err.message;
318+
var bufferSize = lengthBytesUTF8(msg) + 1;
319+
var buffer = _malloc(bufferSize);
320+
stringToUTF8(msg, buffer, bufferSize);
321+
dynCall_viii(cb, idPtr, null, buffer);
322+
});
323+
},
324+
ThirdwebGetBlockWithTransactions: async function (taskId, blockNumber, cb) {
325+
// convert taskId from pointer to str and allocate it to keep in memory
326+
var id = UTF8ToString(taskId);
327+
var idSize = lengthBytesUTF8(id) + 1;
328+
var idPtr = _malloc(idSize);
329+
stringToUTF8(id, idPtr, idSize);
330+
// execute bridge call
331+
window.bridge
332+
.getBlockWithTransactions(UTF8ToString(blockNumber))
333+
.then((returnStr) => {
334+
var bufferSize = lengthBytesUTF8(returnStr) + 1;
335+
var buffer = _malloc(bufferSize);
336+
stringToUTF8(returnStr, buffer, bufferSize);
337+
dynCall_viii(cb, idPtr, buffer, null);
338+
})
339+
.catch((err) => {
340+
var msg = err.message;
341+
var bufferSize = lengthBytesUTF8(msg) + 1;
342+
var buffer = _malloc(bufferSize);
343+
stringToUTF8(msg, buffer, bufferSize);
344+
dynCall_viii(cb, idPtr, null, buffer);
345+
});
346+
},
255347
};
256348

257349
mergeInto(LibraryManager.library, plugin);

Assets/Thirdweb/Core/Scripts/AccountAbstraction/Core/SmartWallet.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ private async Task<RpcResponseMessage> CreateUserOpAndSend(RpcRequestMessage req
182182

183183
var paramList = JsonConvert.DeserializeObject<List<object>>(JsonConvert.SerializeObject(requestMessage.RawParameters));
184184
var transactionInput = JsonConvert.DeserializeObject<TransactionInput>(JsonConvert.SerializeObject(paramList[0]));
185-
var latestBlock = await Utils.GetBlockByNumber(await Utils.GetLatestBlockNumber());
185+
var latestBlock = await Blocks.GetBlock(await Blocks.GetLatestBlockNumber());
186186
var dummySig = new byte[Constants.DUMMY_SIG_LENGTH];
187187
for (int i = 0; i < Constants.DUMMY_SIG_LENGTH; i++)
188188
dummySig[i] = 0x01;
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System.Numerics;
2+
using System.Threading.Tasks;
3+
using Nethereum.Hex.HexTypes;
4+
using Nethereum.RPC.Eth.DTOs;
5+
6+
namespace Thirdweb
7+
{
8+
public static class Blocks
9+
{
10+
/// <summary>
11+
/// Returns the latest block number
12+
/// </summary>
13+
public static async Task<BigInteger> GetLatestBlockNumber()
14+
{
15+
if (Utils.IsWebGLBuild())
16+
{
17+
return await Bridge.GetLatestBlockNumber();
18+
}
19+
else
20+
{
21+
var hex = await Utils.GetWeb3().Eth.Blocks.GetBlockNumber.SendRequestAsync();
22+
return hex.Value;
23+
}
24+
}
25+
26+
/// <summary>
27+
/// Returns the latest block timestamp
28+
/// </summary>
29+
public static async Task<BigInteger> GetLatestBlockTimestamp()
30+
{
31+
var block = await GetBlock(await GetLatestBlockNumber());
32+
return block.Timestamp.Value;
33+
}
34+
35+
/// <summary>
36+
/// Returns the latest block (with transaction hashes)
37+
/// </summary>
38+
/// <param name="blockNumber">Number of the block to retrieve</param>
39+
public static async Task<BlockWithTransactionHashes> GetBlock(BigInteger blockNumber)
40+
{
41+
if (Utils.IsWebGLBuild())
42+
{
43+
return await Bridge.GetBlock(blockNumber);
44+
}
45+
else
46+
{
47+
return await Utils.GetWeb3().Eth.Blocks.GetBlockWithTransactionsHashesByNumber.SendRequestAsync(new HexBigInteger(blockNumber));
48+
}
49+
}
50+
51+
/// <summary>
52+
/// Returns the latest block with transaction data
53+
/// </summary>
54+
/// <param name="blockNumber">Number of the block to retrieve</param>
55+
public static async Task<BlockWithTransactions> GetBlockWithTransactions(BigInteger blockNumber)
56+
{
57+
if (Utils.IsWebGLBuild())
58+
{
59+
return await Bridge.GetBlockWithTransactions(blockNumber);
60+
}
61+
else
62+
{
63+
return await Utils.GetWeb3().Eth.Blocks.GetBlockWithTransactionsByNumber.SendRequestAsync(new HexBigInteger(blockNumber));
64+
}
65+
}
66+
}
67+
}

Assets/Thirdweb/Core/Scripts/Blocks.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Thirdweb/Core/Scripts/Bridge.cs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Numerics;
34
using System.Runtime.InteropServices;
45
using System.Threading.Tasks;
6+
using Nethereum.RPC.Eth.DTOs;
57
using Newtonsoft.Json;
68
using UnityEngine;
79

@@ -260,6 +262,74 @@ public static async Task<T> SmartWalletCreateSessionKey<T>(string options)
260262
return JsonConvert.DeserializeObject<Result<T>>(result).result;
261263
}
262264

265+
public static async Task<TransactionReceipt> WaitForTransactionResult(string txHash)
266+
{
267+
if (!Utils.IsWebGLBuild())
268+
{
269+
ThirdwebDebug.LogWarning("Interacting with the thirdweb SDK is not fully supported in the editor.");
270+
return default;
271+
}
272+
string taskId = Guid.NewGuid().ToString();
273+
var task = new TaskCompletionSource<string>();
274+
taskMap[taskId] = task;
275+
#if UNITY_WEBGL
276+
ThirdwebWaitForTransactionResult(taskId, txHash, jsCallback);
277+
#endif
278+
string result = await task.Task;
279+
return JsonConvert.DeserializeObject<Result<TransactionReceipt>>(result).result;
280+
}
281+
282+
public static async Task<BigInteger> GetLatestBlockNumber()
283+
{
284+
if (!Utils.IsWebGLBuild())
285+
{
286+
ThirdwebDebug.LogWarning("Interacting with the thirdweb SDK is not fully supported in the editor.");
287+
return BigInteger.Zero;
288+
}
289+
string taskId = Guid.NewGuid().ToString();
290+
var task = new TaskCompletionSource<string>();
291+
taskMap[taskId] = task;
292+
#if UNITY_WEBGL
293+
ThirdwebGetLatestBlockNumber(taskId, jsCallback);
294+
#endif
295+
string result = await task.Task;
296+
return JsonConvert.DeserializeObject<Result<BigInteger>>(result).result;
297+
}
298+
299+
public static async Task<BlockWithTransactionHashes> GetBlock(BigInteger blockNumber)
300+
{
301+
if (!Utils.IsWebGLBuild())
302+
{
303+
ThirdwebDebug.LogWarning("Interacting with the thirdweb SDK is not fully supported in the editor.");
304+
return null;
305+
}
306+
string taskId = Guid.NewGuid().ToString();
307+
var task = new TaskCompletionSource<string>();
308+
taskMap[taskId] = task;
309+
#if UNITY_WEBGL
310+
ThirdwebGetBlock(taskId, blockNumber.ToString(), jsCallback);
311+
#endif
312+
string result = await task.Task;
313+
return JsonConvert.DeserializeObject<Result<BlockWithTransactionHashes>>(result).result;
314+
}
315+
316+
public static async Task<BlockWithTransactions> GetBlockWithTransactions(BigInteger blockNumber)
317+
{
318+
if (!Utils.IsWebGLBuild())
319+
{
320+
ThirdwebDebug.LogWarning("Interacting with the thirdweb SDK is not fully supported in the editor.");
321+
return null;
322+
}
323+
string taskId = Guid.NewGuid().ToString();
324+
var task = new TaskCompletionSource<string>();
325+
taskMap[taskId] = task;
326+
#if UNITY_WEBGL
327+
ThirdwebGetBlockWithTransactions(taskId, blockNumber.ToString(), jsCallback);
328+
#endif
329+
string result = await task.Task;
330+
return JsonConvert.DeserializeObject<Result<BlockWithTransactions>>(result).result;
331+
}
332+
263333
#if UNITY_WEBGL
264334
[DllImport("__Internal")]
265335
private static extern string ThirdwebInvoke(string taskId, string route, string payload, Action<string, string, string> cb);
@@ -283,6 +353,15 @@ public static async Task<T> SmartWalletCreateSessionKey<T>(string options)
283353
private static extern string ThirdwebSmartWalletRemoveAdmin(string taskId, string admin, Action<string, string, string> cb);
284354
[DllImport("__Internal")]
285355
private static extern string ThirdwebSmartWalletCreateSessionKey(string taskId, string options, Action<string, string, string> cb);
356+
[DllImport("__Internal")]
357+
private static extern string ThirdwebWaitForTransactionResult(string taskId, string txHash, Action<string, string, string> cb);
358+
[DllImport("__Internal")]
359+
private static extern string ThirdwebGetLatestBlockNumber(string taskId, Action<string, string, string> cb);
360+
[DllImport("__Internal")]
361+
private static extern string ThirdwebGetBlock(string taskId, string blockNumber, Action<string, string, string> cb);
362+
[DllImport("__Internal")]
363+
private static extern string ThirdwebGetBlockWithTransactions(string taskId, string blockNumber, Action<string, string, string> cb);
364+
286365
#endif
287366
}
288367
}

Assets/Thirdweb/Core/Scripts/Marketplace.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ public async Task<TransactionResult> CreateListing(CreateListingInput input)
279279
Quantity = BigInteger.Parse(input.quantity ?? "1"),
280280
Currency = input.currencyContractAddress ?? Utils.NativeTokenAddress,
281281
PricePerToken = BigInteger.Parse(input.pricePerToken),
282-
StartTimestamp = (BigInteger)(input.startTimestamp ?? await Utils.GetCurrentBlockTimeStamp() + 60),
282+
StartTimestamp = input.startTimestamp ?? await Blocks.GetLatestBlockTimestamp() + 60,
283283
EndTimestamp = (BigInteger)(input.endTimestamp ?? Utils.GetUnixTimeStampNow() + 60 * 60 * 24 * 7),
284284
Reserved = input.isReservedListing ?? false,
285285
}
@@ -687,7 +687,7 @@ public async Task<TransactionResult> CreateAuction(CreateAuctionInput input)
687687
BuyoutBidAmount = BigInteger.Parse(input.buyoutBidAmount.ToWei()),
688688
TimeBufferInSeconds = ulong.Parse(input.timeBufferInSeconds ?? "900"),
689689
BidBufferBps = ulong.Parse(input.bidBufferBps ?? "500"),
690-
StartTimestamp = (ulong)(input.startTimestamp ?? await Utils.GetCurrentBlockTimeStamp() + 60),
690+
StartTimestamp = (ulong)(input.startTimestamp ?? await Blocks.GetLatestBlockTimestamp() + 60),
691691
EndTimestamp = (ulong)(input.endTimestamp ?? Utils.GetUnixTimeStampNow() + 60 * 60 * 24 * 7),
692692
}
693693
}

Assets/Thirdweb/Core/Scripts/Pack.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ public async Task<TransactionResult> CreateTo(string receiverAddress, NewPackInp
311311
Contents = pack.ToPackTokenList(),
312312
NumOfRewardUnits = pack.ToPackRewardUnitsList(),
313313
PackUri = uri.IpfsHash.CidToIpfsUrl(),
314-
OpenStartTimestamp = await Utils.GetCurrentBlockTimeStamp(),
314+
OpenStartTimestamp = await Blocks.GetLatestBlockTimestamp(),
315315
AmountDistributedPerOpen = BigInteger.Parse(pack.rewardsPerPack),
316316
Recipient = receiverAddress
317317
}

Assets/Thirdweb/Core/Scripts/Transaction.cs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
using System;
21
using System.Numerics;
32
using System.Threading.Tasks;
43
using Nethereum.Hex.HexTypes;
54
using Nethereum.RPC.Eth.DTOs;
65
using Nethereum.RPC.Eth.Transactions;
7-
using Nethereum.Web3;
86
using Newtonsoft.Json;
97
using UnityEngine;
108
using MinimalForwarder = Thirdweb.Contracts.Forwarder.ContractDefinition;
@@ -374,17 +372,21 @@ public static async Task<TransactionResult> WaitForTransactionResult(string txHa
374372
public static async Task<TransactionReceipt> WaitForTransactionResultRaw(string txHash)
375373
{
376374
if (Utils.IsWebGLBuild())
377-
throw new UnityException("WaitForTransactionResult is not supported in WebGL builds.");
378-
379-
var web3 = Utils.GetWeb3();
380-
var receipt = await web3.TransactionReceiptPolling.PollForReceiptAsync(txHash);
381-
if (receipt.Failed())
382375
{
383-
var reason = await web3.Eth.GetContractTransactionErrorReason.SendRequestAsync(txHash);
384-
if (!string.IsNullOrEmpty(reason))
385-
throw new UnityException($"Transaction failed: {reason}");
376+
return await Bridge.WaitForTransactionResult(txHash);
377+
}
378+
else
379+
{
380+
var web3 = Utils.GetWeb3();
381+
var receipt = await web3.TransactionReceiptPolling.PollForReceiptAsync(txHash);
382+
if (receipt.Failed())
383+
{
384+
var reason = await web3.Eth.GetContractTransactionErrorReason.SendRequestAsync(txHash);
385+
if (!string.IsNullOrEmpty(reason))
386+
throw new UnityException($"Transaction failed: {reason}");
387+
}
388+
return receipt;
386389
}
387-
return receipt;
388390
}
389391

390392
private async Task<string> Send()

Assets/Thirdweb/Core/Scripts/Utils.cs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -267,24 +267,6 @@ public static BigInteger GetMaxUint256()
267267
return BigInteger.Parse("115792089237316195423570985008687907853269984665640564039457584007913129639935");
268268
}
269269

270-
public async static Task<BigInteger> GetCurrentBlockTimeStamp()
271-
{
272-
var blockNumber = await GetLatestBlockNumber();
273-
var block = await GetBlockByNumber(blockNumber);
274-
return block.Timestamp.Value;
275-
}
276-
277-
public async static Task<BigInteger> GetLatestBlockNumber()
278-
{
279-
var hex = await Utils.GetWeb3().Eth.Blocks.GetBlockNumber.SendRequestAsync();
280-
return hex.Value;
281-
}
282-
283-
public async static Task<Nethereum.RPC.Eth.DTOs.BlockWithTransactionHashes> GetBlockByNumber(BigInteger blockNumber)
284-
{
285-
return await Utils.GetWeb3().Eth.Blocks.GetBlockWithTransactionsHashesByNumber.SendRequestAsync(new Nethereum.Hex.HexTypes.HexBigInteger(blockNumber));
286-
}
287-
288270
public static string GetDeviceIdentifier()
289271
{
290272
return SystemInfo.deviceUniqueIdentifier;

0 commit comments

Comments
 (0)