From 1c7489357e80c7c689a9a54394256287c2be3496 Mon Sep 17 00:00:00 2001 From: caballoninja Date: Thu, 8 May 2025 18:21:11 -0300 Subject: [PATCH 1/4] Initial Commit Wallet, deploy and mint test. Editor helper not working --- Assets/SequenceSDK/Marketplace/SideKick.meta | 8 + .../Marketplace/SideKick/Tests.meta | 8 + .../SideKick/Tests/SideKickWalletTests.cs | 39 +++ .../Tests/SideKickWalletTests.cs.meta | 11 + .../SideKick/Tests/SidekickERC1155Tests.cs | 83 ++++++ .../Tests/SidekickERC1155Tests.cs.meta | 11 + Assets/SidekickEditor.meta | 8 + Assets/SidekickEditor/SidekickEditor.cs | 49 ++++ Assets/SidekickEditor/SidekickEditor.cs.meta | 11 + .../SidekickEditorController.cs | 81 +++++ .../SidekickEditorController.cs.meta | 11 + .../EmbeddedWallet/SequenceSidekickClient.cs | 277 ++++++++++++++++++ .../SequenceSidekickClient.cs.meta | 11 + .../SequenceSDK/Pay/Transak/NftDataEncoder.cs | 14 +- .../Pay/Transak/TransakNFTCheckout.cs | 4 +- 15 files changed, 622 insertions(+), 4 deletions(-) create mode 100644 Assets/SequenceSDK/Marketplace/SideKick.meta create mode 100644 Assets/SequenceSDK/Marketplace/SideKick/Tests.meta create mode 100644 Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs create mode 100644 Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs.meta create mode 100644 Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs create mode 100644 Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs.meta create mode 100644 Assets/SidekickEditor.meta create mode 100644 Assets/SidekickEditor/SidekickEditor.cs create mode 100644 Assets/SidekickEditor/SidekickEditor.cs.meta create mode 100644 Assets/SidekickEditor/SidekickEditorController.cs create mode 100644 Assets/SidekickEditor/SidekickEditorController.cs.meta create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs.meta diff --git a/Assets/SequenceSDK/Marketplace/SideKick.meta b/Assets/SequenceSDK/Marketplace/SideKick.meta new file mode 100644 index 00000000..8916b6b2 --- /dev/null +++ b/Assets/SequenceSDK/Marketplace/SideKick.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d3f2ac871ca482d49be6994b4018becb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SequenceSDK/Marketplace/SideKick/Tests.meta b/Assets/SequenceSDK/Marketplace/SideKick/Tests.meta new file mode 100644 index 00000000..a4a048dd --- /dev/null +++ b/Assets/SequenceSDK/Marketplace/SideKick/Tests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0241586cbfa27734f92fba37314ed60a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs b/Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs new file mode 100644 index 00000000..66dba143 --- /dev/null +++ b/Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs @@ -0,0 +1,39 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using UnityEngine; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Sequence.Sidekick +{ + public class SequenceSidekickTests + { + SequenceSidekickClient sidekick; + string chainId; + + [SetUp] + public void Setup() + { + sidekick = new SequenceSidekickClient(Chain.TestnetArbitrumSepolia); + chainId = sidekick.Chain.GetChainId(); + + } + + [Test] + public async Task TestGetWalletAddress() + { + try + { + var sidekick = new SequenceSidekickClient(); + string walletAddress = await sidekick.GetWalletAddress(); + Assert.IsNotNull(walletAddress); + } + catch (Exception e) + { + Assert.Fail("Expected no exception, but got: " + e.Message); + } + } + + } +} \ No newline at end of file diff --git a/Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs.meta b/Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs.meta new file mode 100644 index 00000000..bb679998 --- /dev/null +++ b/Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 017246b8d45cfa14d91ee0abf92a13aa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs b/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs new file mode 100644 index 00000000..ea3f00f1 --- /dev/null +++ b/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs @@ -0,0 +1,83 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using UnityEngine; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Sequence.Sidekick +{ + public class SidekickERC1155MintTest + { + private SequenceSidekickClient sidekick; + private string chainId; + private string walletAddress; + + [SetUp] + public void Setup() + { + sidekick = new SequenceSidekickClient(Chain.TestnetArbitrumSepolia); + chainId = sidekick.Chain.GetChainId(); + } + + + [Test] + public async Task DeployERC1155() + { + try + { + walletAddress = await sidekick.GetWalletAddress(); + string recipientAddress = JObject.Parse(walletAddress)["address"]?.ToString(); + + var deployBody = new + { + defaultAdmin = recipientAddress, + minter = recipientAddress, + name = "MYTESTERC1155" + }; + + + string deployJson = JsonConvert.SerializeObject(deployBody); + + string deployResult = await sidekick.DeployERC1155(chainId, deployJson); + + Debug.Log("Deploy result: " + deployResult); + Assert.IsNotNull(deployResult, "Deploy result must not be null"); + } + catch (Exception e) + { + Assert.Fail("ERC1155 deploy flow failed: " + e.Message); + } + } + + + [Test] + public async Task MintERC1155() + { + try + { + walletAddress = await sidekick.GetWalletAddress(); + + string recipientAddress = JObject.Parse(walletAddress)["address"]?.ToString(); + + var mintBody = new + { + recipient = recipientAddress, + id = "0", + amount = "1", + data = "0x00" + }; + string mintJson = JsonConvert.SerializeObject(mintBody); + string mintResult = await sidekick.MintERC1155(chainId, "0x63c12baa017b2bcb6855d83506500edcac423c3c", mintJson); + + Debug.Log("Mint result: " + mintResult); + + Assert.IsNotNull(mintResult, "Mint result must not be null"); + } + catch (Exception e) + { + Assert.Fail("ERC1155 flow failed: " + e.Message); + } + } + } +} \ No newline at end of file diff --git a/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs.meta b/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs.meta new file mode 100644 index 00000000..94e8d9f4 --- /dev/null +++ b/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 71b6d06c155472b4699f44b7dbb09b93 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SidekickEditor.meta b/Assets/SidekickEditor.meta new file mode 100644 index 00000000..a1e6ba8c --- /dev/null +++ b/Assets/SidekickEditor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ca60c91a2b637284081d37835cd4523e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SidekickEditor/SidekickEditor.cs b/Assets/SidekickEditor/SidekickEditor.cs new file mode 100644 index 00000000..1e286187 --- /dev/null +++ b/Assets/SidekickEditor/SidekickEditor.cs @@ -0,0 +1,49 @@ +using UnityEditor; +using UnityEngine; +using Sequence.Sidekick; + +[CustomEditor(typeof(SidekickEditorController))] +public class SidekickEditor : Editor +{ + + public override void OnInspectorGUI() + { + SidekickEditorController controller = (SidekickEditorController)target; + + serializedObject.Update(); + + + #region Deploy ERC1155 + + EditorGUILayout.LabelField("Deploy ERC1155"); + + controller.deployDefaultAdmin = EditorGUILayout.TextField("Default Admin", controller.deployDefaultAdmin); + controller.deployMinter = EditorGUILayout.TextField("Minter", controller.deployMinter); + controller.deployName = EditorGUILayout.TextField("Name", controller.deployName); + + if (GUILayout.Button("Deploy ERC1155")) + { + controller.DeployERC1155(controller.deployDefaultAdmin, controller.deployMinter, controller.deployName); + } + + #endregion + + #region Mint ERC1155 + + EditorGUILayout.LabelField("Mint ERC1155"); + controller.MintContractAddress = EditorGUILayout.TextField("Contract Address", controller.MintContractAddress); + controller.MintRecipientAddress = EditorGUILayout.TextField("Recipient Address", controller.MintRecipientAddress); + controller.MintId = EditorGUILayout.TextField("ID", controller.MintId); + controller.MintAmount = EditorGUILayout.TextField("Amount", controller.MintAmount); + controller.MintData = EditorGUILayout.TextField("Data", controller.MintData); + + if (GUILayout.Button("Mint ERC1155")) + { + controller.MintERC1155(controller.MintContractAddress, controller.MintRecipientAddress, controller.MintId, controller.MintAmount, controller.MintData); + } + + #endregion + + base.OnInspectorGUI(); + } +} \ No newline at end of file diff --git a/Assets/SidekickEditor/SidekickEditor.cs.meta b/Assets/SidekickEditor/SidekickEditor.cs.meta new file mode 100644 index 00000000..3984d6ce --- /dev/null +++ b/Assets/SidekickEditor/SidekickEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: be52a77155b094f4eb30b94267580886 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SidekickEditor/SidekickEditorController.cs b/Assets/SidekickEditor/SidekickEditorController.cs new file mode 100644 index 00000000..d1a6d274 --- /dev/null +++ b/Assets/SidekickEditor/SidekickEditorController.cs @@ -0,0 +1,81 @@ +using UnityEditor; +using UnityEngine; +using Sequence; +using Sequence.Sidekick; + +public class SidekickEditorController : MonoBehaviour +{ + + private SequenceSidekickClient sidekick = new SequenceSidekickClient(Chain.TestnetArbitrumSepolia); + + #region Deploy ERC1155 + + public string deployDefaultAdmin = "0xeBc14a7f27824A13A6a0c58a4C5C34d35c9F43a8"; + public string deployMinter = "0xeBc14a7f27824A13A6a0c58a4C5C34d35c9F43a8"; + public string deployName = "myerc"; + + public async void DeployERC1155(string defaultAdmin, string minter, string name) + { + var deployJson = new + { + defaultAdmin = defaultAdmin, + minter = minter, + name = name + }; + string jsonString = JsonUtility.ToJson(deployJson); + + Debug.Log(jsonString); + + EditorApplication.delayCall += async () => + { + try + { + string result = await sidekick.DeployERC1155(sidekick.Chain.GetChainId(), jsonString); + Debug.Log("Deploy result: " + result); + } + catch (System.Exception ex) + { + Debug.LogError("Deploy ERC1155 failed: " + ex.Message); + } + }; + } + + #endregion + + #region Mint ERC1155 + + [HideInInspector] public string MintContractAddress; + public string MintRecipientAddress { get; set; } + public string MintId { get; set; } + public string MintAmount { get; set; } + public string MintData { get; set; } + + public async void MintERC1155(string contractAddress, string recipient, string id, string amount, string data) + { + var mintJson = new + { + recipient = recipient, + id = id, + amount = amount, + data = data + }; + string jsonString = JsonUtility.ToJson(mintJson); + Debug.Log(jsonString); + + EditorApplication.delayCall += async () => + { + try + { + string result = await sidekick.MintERC1155(sidekick.Chain.GetChainId(), contractAddress, jsonString); + Debug.Log("Mint result: " + result); + } + catch (System.Exception ex) + { + Debug.LogError("Mint ERC1155 failed: " + ex.Message); + } + }; + } + + #endregion + +} diff --git a/Assets/SidekickEditor/SidekickEditorController.cs.meta b/Assets/SidekickEditor/SidekickEditorController.cs.meta new file mode 100644 index 00000000..39cbf572 --- /dev/null +++ b/Assets/SidekickEditor/SidekickEditorController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 40b315f114ec9004d907e97fe436eb55 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs new file mode 100644 index 00000000..351e49eb --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs @@ -0,0 +1,277 @@ +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace Sequence.Sidekick +{ + public class SequenceSidekickClient + { + private static readonly HttpClient client = new(); + private string baseUrl = "http://localhost:3000"; + private string secretKey = "ultrasecretkey"; + + public Chain Chain; + + public SequenceSidekickClient() { } + + public SequenceSidekickClient(Chain chain) + { + Chain = chain; + } + + #region HttpRequests + private async Task GetAsync(string endpoint, Dictionary headers = null) + { + using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, baseUrl + endpoint)) + { + if (headers != null) + { + foreach (var header in headers) + { + request.Headers.Add(header.Key, header.Value); + } + } + + HttpResponseMessage response = await client.SendAsync(request); + response.EnsureSuccessStatusCode(); + return await response.Content.ReadAsStringAsync(); + } + } + + private async Task PostAsync(string endpoint, string json) + { + string url = baseUrl + endpoint; + + using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url)) + { + request.Headers.Add("x-secret-key", secretKey); + + var content = new StringContent(json, Encoding.UTF8, "application/json"); + request.Content = content; + + try + { + HttpResponseMessage response = await client.SendAsync(request); + string responseContent = await response.Content.ReadAsStringAsync(); + response.EnsureSuccessStatusCode(); + return responseContent; + } + catch (HttpRequestException e) + { + throw; + } + } + } + + #endregion + + #region Wallet + public async Task GetWalletAddress() + { + return await GetAsync("/sidekick/wallet-address"); + } + + #endregion + + #region Contract + public async Task ReadContract(string chainId, string address, string functionName, string json) + { + return await PostAsync($"/read/contract/{chainId}/{address}/{functionName}", json); + } + + public async Task WriteContract(string chainId, string address, string functionName, string json) + { + return await PostAsync($"/write/contract/{chainId}/{address}/{functionName}", json); + } + + public async Task GetAllContracts() + { + return await GetAsync("/contract/getAll"); + } + + public async Task GetContract(string address) + { + return await GetAsync($"/contract/get/{address}"); + } + + public async Task IsContractDeployed(string chainId, string address) + { + return await GetAsync($"/contract/isDeployed/{chainId}/{address}"); + } + + public async Task DeployContract(string chainId, string json) + { + return await PostAsync($"/deploy/contract/{chainId}", json); + } + + public async Task ImportContractsFromBuilder(string projectId, string json) + { + return await PostAsync($"/contract/importAllFromBuilder/{projectId}", json); + } + + public async Task AddContract(string json) + { + return await PostAsync("/contract/add", json); + } + + #endregion + + #region ERC20 + public async Task TransferERC20(string chainId, string address, string json) + { + return await PostAsync($"/write/erc20/{chainId}/{address}/transfer", json); + } + + public async Task ApproveERC20(string chainId, string address, string json) + { + + return await PostAsync($"/write/erc20/{chainId}/{address}/approve", json); + } + + public async Task MintERC20(string chainId, string address, string json) + { + return await PostAsync($"/write/erc20/{chainId}/{address}/mint", json); + } + + public async Task TransferFromERC20(string chainId, string address, string json) + { + return await PostAsync($"/write/erc20/{chainId}/{address}/transferFrom", json); + } + + public async Task DeployERC20(string chainId, string json) + { + return await PostAsync($"/deploy/erc20/{chainId}", json); + } + + #endregion + + #region ERC721 + + public async Task SafeMintERC721(string chainId, string address, string json) + { + return await PostAsync($"/write/erc721/{chainId}/{address}/safeMint", json); + } + + public async Task SafeMintBatchERC721(string chainId, string address, string json) + { + return await PostAsync($"/write/erc721/{chainId}/{address}/safeMintBatch", json); + } + + public async Task BalanceOfERC721(string chainId, string address) + { + return await GetAsync($"/read/erc721/{chainId}/{address}/balanceOf"); + } + + public async Task DeployERC721(string chainId, string json) + { + return await PostAsync($"/deploy/erc721/{chainId}", json); + } + + #endregion + + #region ERC1155 + + public async Task MintERC1155(string chainId, string address, string json) + { + return await PostAsync($"/write/erc1155/{chainId}/{address}/mint", json); + } + + public async Task MintBatchERC1155(string chainId, string address, string json) + { + return await PostAsync($"/write/erc1155/{chainId}/{address}/mintBatch", json); + } + + public async Task GrantRoleERC1155(string chainId, string address, string json) + { + return await PostAsync($"/write/erc1155/{chainId}/{address}/grantRole", json); + } + + public async Task HasRoleERC1155(string chainId, string address) + { + return await GetAsync($"/read/erc1155/{chainId}/{address}/hasRole"); + } + + public async Task MinterRoleERC1155(string chainId, string address) + { + return await GetAsync($"/read/erc1155/{chainId}/{address}/minterRole"); + } + + public async Task BalanceOfERC1155(string chainId, string address) + { + return await GetAsync($"/read/erc1155/{chainId}/{address}/balanceOf"); + } + + public async Task DeployERC1155(string chainId, string json) + { + return await PostAsync($"/deploy/erc1155/{chainId}", json); + } + + #endregion + + #region Transactions + public async Task GetAllTransactions() + { + return await GetAsync("/transactions"); + } + + public async Task GetTransaction(string txHash) + { + return await GetAsync($"/transactions/{txHash}"); + } + + #endregion + + #region Webhooks + public async Task AddWebhook(string json) + { + return await PostAsync("/webhook/add", json); + } + + public async Task RemoveWebhook(string json) + { + return await PostAsync("/webhook/remove", json); + } + + public async Task RemoveAllWebhooks() + { + return await PostAsync("/webhook/removeAll", ""); + } + + public async Task GetAllWebhooks() + { + return await GetAsync("/webhook/getAll"); + } + + #endregion + + #region Jobs + public async Task StartERC20RewardsJob(string chainId, string address, string json) + { + return await PostAsync($"/jobs/erc20/rewards/{chainId}/{address}/start", json); + } + + public async Task StopERC20RewardsJob(string chainId, string address, string json) + { + return await PostAsync($"/jobs/erc20/rewards/{chainId}/{address}/stop", json); + } + + public async Task GetAllJobs() + { + return await GetAsync("/jobs"); + } + + public async Task GetJob(string jobId) + { + return await GetAsync($"/jobs/{jobId}"); + } + + public async Task CleanJobs(string json) + { + return await PostAsync("/jobs/clean", json); + } + + #endregion + } +} diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs.meta b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs.meta new file mode 100644 index 00000000..3f91bcd2 --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3c6ce8681ba99e3429b20ec48ba54335 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Pay/Transak/NftDataEncoder.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/Pay/Transak/NftDataEncoder.cs index fdf6873d..241dba55 100644 --- a/Packages/Sequence-Unity/Sequence/SequenceSDK/Pay/Transak/NftDataEncoder.cs +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Pay/Transak/NftDataEncoder.cs @@ -1,6 +1,7 @@ using System; using Newtonsoft.Json; using Sequence.Utils; +using UnityEngine; // Make sure this is included for logging namespace Sequence.Pay.Transak { @@ -8,9 +9,16 @@ public class NftDataEncoder { public static string Encode(TransakNftData item) { - string itemJson = JsonConvert.SerializeObject(new [] { item }); + string itemJson = JsonConvert.SerializeObject(new[] { item }); + Debug.Log("JSON Serialized:\n" + itemJson); + string itemJsonBase64 = itemJson.StringToBase64(); - return Uri.EscapeDataString(itemJsonBase64); + Debug.Log("Base64 Encoded (with padding):\n" + itemJsonBase64); + + string encoded = Uri.EscapeDataString(itemJsonBase64); + Debug.Log("URL Encoded:\n" + encoded); + + return encoded; } } -} \ No newline at end of file +} diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Pay/Transak/TransakNFTCheckout.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/Pay/Transak/TransakNFTCheckout.cs index 3343ca11..96486562 100644 --- a/Packages/Sequence-Unity/Sequence/SequenceSDK/Pay/Transak/TransakNFTCheckout.cs +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Pay/Transak/TransakNFTCheckout.cs @@ -107,13 +107,15 @@ public async Task OpenNFTCheckoutLink(TransakNftData item, TransakContractId con Application.OpenURL(link); } - private async Task GetNFTCheckoutLink(TransakNftData item, string callData, Address contractAddress, TransakContractId contractId) + private async Task GetNFTCheckoutLink(TransakNftData item, string callData, Address contractAddress, TransakContractId contractId) { if (contractId.Chain != _chain) { throw new ArgumentException($"The provided {nameof(contractId)} is not for the same chain as the current instance of {nameof(TransakNFTCheckout)}, given: {contractId.Chain}, expected: {_chain}"); } + Debug.Log(callData); + string transakCallData = CallDataCompressor.Compress(callData); string baseUrl = "https://global.transak.com"; From 5efa55009be71c47bf19b4604f4e1ecb39700321 Mon Sep 17 00:00:00 2001 From: caballoninja Date: Tue, 13 May 2025 11:03:19 -0300 Subject: [PATCH 2/4] deploy payload and editor gui update to enable editor calls reading json body correctly --- Assets/SidekickEditor/SidekickEditor.cs | 3 --- .../SidekickEditorController.cs | 19 +++++++++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Assets/SidekickEditor/SidekickEditor.cs b/Assets/SidekickEditor/SidekickEditor.cs index 1e286187..dfbc793b 100644 --- a/Assets/SidekickEditor/SidekickEditor.cs +++ b/Assets/SidekickEditor/SidekickEditor.cs @@ -10,9 +10,6 @@ public override void OnInspectorGUI() { SidekickEditorController controller = (SidekickEditorController)target; - serializedObject.Update(); - - #region Deploy ERC1155 EditorGUILayout.LabelField("Deploy ERC1155"); diff --git a/Assets/SidekickEditor/SidekickEditorController.cs b/Assets/SidekickEditor/SidekickEditorController.cs index d1a6d274..2d15f152 100644 --- a/Assets/SidekickEditor/SidekickEditorController.cs +++ b/Assets/SidekickEditor/SidekickEditorController.cs @@ -10,21 +10,21 @@ public class SidekickEditorController : MonoBehaviour #region Deploy ERC1155 - public string deployDefaultAdmin = "0xeBc14a7f27824A13A6a0c58a4C5C34d35c9F43a8"; - public string deployMinter = "0xeBc14a7f27824A13A6a0c58a4C5C34d35c9F43a8"; - public string deployName = "myerc"; + public string deployDefaultAdmin { get; set; } + public string deployMinter { get; set; } + public string deployName { get; set; } public async void DeployERC1155(string defaultAdmin, string minter, string name) { - var deployJson = new + var deployPayload = new DeployERC1155Payload { defaultAdmin = defaultAdmin, minter = minter, name = name }; - string jsonString = JsonUtility.ToJson(deployJson); + string jsonString = JsonUtility.ToJson(deployPayload); - Debug.Log(jsonString); + Debug.Log("Deploying ERC1155:" + jsonString); EditorApplication.delayCall += async () => { @@ -79,3 +79,10 @@ public async void MintERC1155(string contractAddress, string recipient, string i #endregion } +[System.Serializable] +public class DeployERC1155Payload +{ + public string defaultAdmin; + public string minter; + public string name; +} From ba3d3eebc9492ae290b73f05f9a05d8d93db807b Mon Sep 17 00:00:00 2001 From: caballoninja Date: Tue, 27 May 2025 10:40:13 -0300 Subject: [PATCH 3/4] Updates to editor controller --- Assets/DeployedContractAddressExtractor.cs | 36 ++ .../DeployedContractAddressExtractor.cs.meta | 11 + Assets/Editor/SidekickDockerUtility.cs | 181 ++++++ Assets/Editor/SidekickDockerUtility.cs.meta | 11 + Assets/NewToken.asset | 17 + Assets/NewToken.asset.meta | 8 + .../SideKick/Tests/SidekickERC1155Tests.cs | 4 +- Assets/SidekickEditor/SidekickEditor.cs | 384 ++++++++++++- .../SidekickEditorController.cs | 534 +++++++++++++++++- .../SequenceSDK/Config/SidekickConfig.cs | 7 + .../SequenceSDK/Config/SidekickConfig.cs.meta | 11 + .../EmbeddedWallet/SequenceSidekickClient.cs | 109 ++-- .../Ethereum/Contract/ScriptableObjects.meta | 8 + .../ScriptableObjects/ERC1155Scriptable.cs | 27 + .../ERC1155Scriptable.cs.meta | 11 + .../ScriptableObjects/ERC20Scriptable.cs | 21 + .../ScriptableObjects/ERC20Scriptable.cs.meta | 11 + .../ScriptableObjects/ERC721Scriptable.cs | 21 + .../ERC721Scriptable.cs.meta | 11 + 19 files changed, 1314 insertions(+), 109 deletions(-) create mode 100644 Assets/DeployedContractAddressExtractor.cs create mode 100644 Assets/DeployedContractAddressExtractor.cs.meta create mode 100644 Assets/Editor/SidekickDockerUtility.cs create mode 100644 Assets/Editor/SidekickDockerUtility.cs.meta create mode 100644 Assets/NewToken.asset create mode 100644 Assets/NewToken.asset.meta create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/Config/SidekickConfig.cs create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/Config/SidekickConfig.cs.meta create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects.meta create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC1155Scriptable.cs create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC1155Scriptable.cs.meta create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC20Scriptable.cs create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC20Scriptable.cs.meta create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC721Scriptable.cs create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC721Scriptable.cs.meta diff --git a/Assets/DeployedContractAddressExtractor.cs b/Assets/DeployedContractAddressExtractor.cs new file mode 100644 index 00000000..41f9aab7 --- /dev/null +++ b/Assets/DeployedContractAddressExtractor.cs @@ -0,0 +1,36 @@ +namespace Sequence +{ + public static class ReceiptExtractor + { + public static string ExtractFirstContractAddressExceptOwn(TransactionReceipt receipt, string ownContractAddress) + { + ownContractAddress = ownContractAddress?.ToLower(); + + if (!string.IsNullOrEmpty(receipt.contractAddress)) + { + var contractAddrLower = receipt.contractAddress.ToLower(); + if (contractAddrLower != ownContractAddress) + { + return contractAddrLower; + } + } + + if (receipt.logs != null) + { + foreach (var log in receipt.logs) + { + if (!string.IsNullOrEmpty(log.address)) + { + var addrLower = log.address.ToLower(); + if (addrLower != ownContractAddress) + { + return addrLower; + } + } + } + } + + return null; + } + } +} diff --git a/Assets/DeployedContractAddressExtractor.cs.meta b/Assets/DeployedContractAddressExtractor.cs.meta new file mode 100644 index 00000000..10e0b143 --- /dev/null +++ b/Assets/DeployedContractAddressExtractor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 41194a16e50bdba48849569c409ac9dd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SidekickDockerUtility.cs b/Assets/Editor/SidekickDockerUtility.cs new file mode 100644 index 00000000..c13e7c7b --- /dev/null +++ b/Assets/Editor/SidekickDockerUtility.cs @@ -0,0 +1,181 @@ +using UnityEditor; +using UnityEngine; +using System.Diagnostics; +using System.IO; +using System.Linq; + +public static class SidekickDockerUtility +{ + private static SidekickConfig config; + + private static string SidekickPath + { + get + { + if (config == null) + { + config = Resources.Load("SidekickConfig"); + if (config == null) + { + UnityEngine.Debug.LogError("Could not load SidekickConfig from Resources."); + return string.Empty; + } + } + return config.path; + } + } + + [MenuItem("Sequence Dev/Start Sidekick", false, 0)] + private static void StartSidekick() + { + if (IsSidekickRunning()) return; + + EnsureDockerDesktopRunning(); + + RunCommand("pnpm docker:restart", SidekickPath); + } + + [MenuItem("Sequence Dev/Start Sidekick", true)] + private static bool ValidateStart() => !IsSidekickRunning(); + + [MenuItem("Sequence Dev/Stop Sidekick", false, 1)] + private static void StopSidekick() + { + if (!IsSidekickRunning()) return; + + RunCommand("pnpm docker:stop", SidekickPath); + } + + [MenuItem("Sequence Dev/Stop Sidekick", true)] + private static bool ValidateStop() => IsSidekickRunning(); + + private static void RunCommand(string command, string workingDirectory) + { + if (string.IsNullOrEmpty(workingDirectory) || !Directory.Exists(workingDirectory)) + { + UnityEngine.Debug.LogError($"Sidekick path not set or invalid: {workingDirectory}"); + return; + } + + ProcessStartInfo psi = new ProcessStartInfo + { + FileName = "cmd.exe", + Arguments = $"/c {command}", + WorkingDirectory = workingDirectory, + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true + }; + + Process process = new Process { StartInfo = psi }; + + process.OutputDataReceived += (sender, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + UnityEngine.Debug.Log($"[Docker] {e.Data}"); + }; + + process.ErrorDataReceived += (sender, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + UnityEngine.Debug.LogWarning($"[Docker] {e.Data}"); + }; + + process.Start(); + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + } + + private static void EnsureDockerDesktopRunning() + { + const int maxWaitTimeSeconds = 120; + const int pollIntervalMs = 2000; + + if (!Process.GetProcessesByName("Docker Desktop").Any()) + { + string dockerDesktopPath = @"C:\Program Files\Docker\Docker\Docker Desktop.exe"; + if (File.Exists(dockerDesktopPath)) + { + Process.Start(dockerDesktopPath); + } + else + { + UnityEngine.Debug.LogWarning("[Docker] Docker Desktop not found at default path."); + return; + } + } + + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + while (stopwatch.Elapsed.TotalSeconds < maxWaitTimeSeconds) + { + if (IsDockerDaemonReady()) + { + return; + } + + System.Threading.Thread.Sleep(pollIntervalMs); + } + + UnityEngine.Debug.LogError("[Docker] Timed out waiting for Docker to become ready."); + } + + private static bool IsDockerDaemonReady() + { + try + { + ProcessStartInfo psi = new ProcessStartInfo + { + FileName = "cmd.exe", + Arguments = "/c docker info", + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true, + UseShellExecute = false + }; + + using (Process process = Process.Start(psi)) + { + process.WaitForExit(3000); + + string output = process.StandardOutput.ReadToEnd(); + string error = process.StandardError.ReadToEnd(); + + return process.ExitCode == 0 && output.Contains("Server Version"); + } + } + catch + { + return false; + } + } + + private static bool IsSidekickRunning() + { + try + { + var psi = new ProcessStartInfo + { + FileName = "cmd.exe", + Arguments = "/c docker ps --format \"{{.Names}}\"", + RedirectStandardOutput = true, + UseShellExecute = false, + CreateNoWindow = true + }; + + using (var process = Process.Start(psi)) + { + process.WaitForExit(); + var output = process.StandardOutput.ReadToEnd(); + + return output.Contains("sidekick"); + } + } + catch + { + return false; + } + } +} diff --git a/Assets/Editor/SidekickDockerUtility.cs.meta b/Assets/Editor/SidekickDockerUtility.cs.meta new file mode 100644 index 00000000..9fe7371d --- /dev/null +++ b/Assets/Editor/SidekickDockerUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a726ece5a906fca4393ef76dfabe8e00 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NewToken.asset b/Assets/NewToken.asset new file mode 100644 index 00000000..5c71e260 --- /dev/null +++ b/Assets/NewToken.asset @@ -0,0 +1,17 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f43439d1f99de164fb5b87ee45ff3e5c, type: 3} + m_Name: NewToken + m_EditorClassIdentifier: + contractAddress: 0x5f6e8810da77cb4762bfa5bdd2f6993bc9cd72a1 + specifyBurnAddress: 0 + linkedGameObject: {fileID: 0} diff --git a/Assets/NewToken.asset.meta b/Assets/NewToken.asset.meta new file mode 100644 index 00000000..133e29c4 --- /dev/null +++ b/Assets/NewToken.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 42986f857e82b284886ac8a43d483ab3 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs b/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs index ea3f00f1..63125f2b 100644 --- a/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs +++ b/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs @@ -39,7 +39,7 @@ public async Task DeployERC1155() string deployJson = JsonConvert.SerializeObject(deployBody); - string deployResult = await sidekick.DeployERC1155(chainId, deployJson); + string deployResult = await sidekick.DeployERC1155(deployJson); Debug.Log("Deploy result: " + deployResult); Assert.IsNotNull(deployResult, "Deploy result must not be null"); @@ -68,7 +68,7 @@ public async Task MintERC1155() data = "0x00" }; string mintJson = JsonConvert.SerializeObject(mintBody); - string mintResult = await sidekick.MintERC1155(chainId, "0x63c12baa017b2bcb6855d83506500edcac423c3c", mintJson); + string mintResult = await sidekick.MintERC1155("0x63c12baa017b2bcb6855d83506500edcac423c3c", mintJson); Debug.Log("Mint result: " + mintResult); diff --git a/Assets/SidekickEditor/SidekickEditor.cs b/Assets/SidekickEditor/SidekickEditor.cs index dfbc793b..1e128949 100644 --- a/Assets/SidekickEditor/SidekickEditor.cs +++ b/Assets/SidekickEditor/SidekickEditor.cs @@ -1,46 +1,384 @@ using UnityEditor; using UnityEngine; -using Sequence.Sidekick; +using System; [CustomEditor(typeof(SidekickEditorController))] public class SidekickEditor : Editor { - + bool deployFoldout = true; + bool mintFoldout = true; + bool generateFoldout = true; + bool grantRoleFoldout = true; + + ContractType selectedDeployType; + ContractType selectedMintType; + ContractType selectedGenerateType; + + GUIStyle HeaderStyle => new GUIStyle(EditorStyles.label) + { + fontStyle = FontStyle.Bold, + fontSize = 16, + normal = { textColor = new Color(0.9f, 0.9f, 0.9f) } + }; + + GUIStyle FoldoutStyle => new GUIStyle(EditorStyles.foldout) + { + fontStyle = FontStyle.Bold, + fontSize = 14, + normal = { textColor = new Color(0.8f, 0.8f, 0.8f) }, + hover = { textColor = Color.white }, + active = { textColor = Color.white } + }; + + GUIStyle SectionBoxStyle + { + get + { + var style = new GUIStyle(GUI.skin.box); + style.normal.background = MakeTex(2, 2, new Color(0.15f, 0.15f, 0.15f, 0.7f)); + style.margin = new RectOffset(0, 0, 5, 10); + style.padding = new RectOffset(10, 10, 10, 10); + return style; + } + } + GUIStyle ButtonStyle + { + get + { + var style = new GUIStyle(GUI.skin.button) + { + fontStyle = FontStyle.Bold, + fontSize = 13 + }; + + style.normal.textColor = Color.white; + style.hover.textColor = Color.white; + + return style; + } + } + GUIStyle LabelBoldStyle => new GUIStyle(EditorStyles.label) + { + fontStyle = FontStyle.Bold, + fontSize = 12, + normal = { textColor = Color.white } + }; + public override void OnInspectorGUI() { - SidekickEditorController controller = (SidekickEditorController)target; + var controller = (SidekickEditorController)target; - #region Deploy ERC1155 + EditorGUILayout.Space(8); + EditorGUILayout.LabelField("Sidekick Wallet", HeaderStyle); - EditorGUILayout.LabelField("Deploy ERC1155"); + GUILayout.Space(6); + if (GUILayout.Button("Get Wallet Address", ButtonStyle, GUILayout.Height(28))) + controller.GetWalletAddress(); - controller.deployDefaultAdmin = EditorGUILayout.TextField("Default Admin", controller.deployDefaultAdmin); - controller.deployMinter = EditorGUILayout.TextField("Minter", controller.deployMinter); - controller.deployName = EditorGUILayout.TextField("Name", controller.deployName); + //GUILayout.Space(6); + //if (GUILayout.Button("Get Contracts", ButtonStyle, GUILayout.Height(28))) + // controller.GetContracts(); - if (GUILayout.Button("Deploy ERC1155")) + EditorGUILayout.Space(14); + + #region Deploy + deployFoldout = EditorGUILayout.Foldout(deployFoldout, "Deploy", true, FoldoutStyle); + if (deployFoldout) { - controller.DeployERC1155(controller.deployDefaultAdmin, controller.deployMinter, controller.deployName); + using (new EditorGUILayout.VerticalScope(SectionBoxStyle)) + { + selectedDeployType = (ContractType)EditorGUILayout.EnumPopup("Contract Type", selectedDeployType); + + EditorGUILayout.Space(); + + switch (selectedDeployType) + { + case ContractType.CurrencyToken: + controller.DeployERC20InitialOwner = EditorGUILayout.TextField("Initial Owner", controller.DeployERC20InitialOwner); + controller.DeployERC20Name = EditorGUILayout.TextField("Name", controller.DeployERC20Name); + controller.DeployERC20Symbol = EditorGUILayout.TextField("Symbol", controller.DeployERC20Symbol); + GUILayout.Space(8); + if (GUILayout.Button("Deploy Currency Token", ButtonStyle, GUILayout.Height(26))) + controller.DeployERC20(); + break; + + case ContractType.NFTContract: + controller.DeployERC721DefaultAdmin = EditorGUILayout.TextField("Default Admin", controller.DeployERC721DefaultAdmin); + controller.DeployERC721Minter = EditorGUILayout.TextField("Minter", controller.DeployERC721Minter); + controller.DeployERC721Name = EditorGUILayout.TextField("Name", controller.DeployERC721Name); + controller.DeployERC721Symbol = EditorGUILayout.TextField("Symbol", controller.DeployERC721Symbol); + GUILayout.Space(8); + if (GUILayout.Button("Deploy NFT Contract", ButtonStyle, GUILayout.Height(26))) + controller.DeployERC721(); + break; + + case ContractType.Web3GameItem: + controller.DeployDefaultAdmin = EditorGUILayout.TextField("Default Admin", controller.DeployDefaultAdmin); + controller.DeployMinter = EditorGUILayout.TextField("Minter", controller.DeployMinter); + controller.DeployName = EditorGUILayout.TextField("Name", controller.DeployName); + GUILayout.Space(8); + if (GUILayout.Button("Deploy Web 3 Game Item", ButtonStyle, GUILayout.Height(26))) + controller.DeployERC1155(); + break; + } + } } + #endregion - #endregion + #region Grant Role + grantRoleFoldout = EditorGUILayout.Foldout(grantRoleFoldout, "Grant Role", true, FoldoutStyle); + if (grantRoleFoldout) + { + using (new EditorGUILayout.VerticalScope(SectionBoxStyle)) + { + controller.SelectedContractRole = (ContractRole)EditorGUILayout.EnumPopup("Role", controller.SelectedContractRole); - #region Mint ERC1155 + switch (controller.SelectedContractRole) + { + case ContractRole.Minter: + controller.GrantRoleRole = "0xdfd8f10cabf255ee49ecf3db8b4502eea7eac26c270f6e5f0f28506f6f3fbb55"; + break; + default: + throw new ArgumentOutOfRangeException(nameof(controller.SelectedContractRole), "Unsupported role"); + } - EditorGUILayout.LabelField("Mint ERC1155"); - controller.MintContractAddress = EditorGUILayout.TextField("Contract Address", controller.MintContractAddress); - controller.MintRecipientAddress = EditorGUILayout.TextField("Recipient Address", controller.MintRecipientAddress); - controller.MintId = EditorGUILayout.TextField("ID", controller.MintId); - controller.MintAmount = EditorGUILayout.TextField("Amount", controller.MintAmount); - controller.MintData = EditorGUILayout.TextField("Data", controller.MintData); + controller.GrantRoleContractAddress = EditorGUILayout.TextField("Contract Address", controller.GrantRoleContractAddress); + controller.GrantRoleAccount = EditorGUILayout.TextField("Account Address", controller.GrantRoleAccount); - if (GUILayout.Button("Mint ERC1155")) + GUILayout.Space(8); + + if (GUILayout.Button("Grant Role", ButtonStyle, GUILayout.Height(26))) + controller.GrantERC1155Role(); + } + } + #endregion + + #region Mint + mintFoldout = EditorGUILayout.Foldout(mintFoldout, "Mint", true, FoldoutStyle); + if (mintFoldout) { - controller.MintERC1155(controller.MintContractAddress, controller.MintRecipientAddress, controller.MintId, controller.MintAmount, controller.MintData); + using (new EditorGUILayout.VerticalScope(SectionBoxStyle)) + { + selectedMintType = (ContractType)EditorGUILayout.EnumPopup("Item Type", selectedMintType); + GUILayout.Space(6); + + switch (selectedMintType) + { + case ContractType.CurrencyToken: + controller.MintERC20ContractAddress = EditorGUILayout.TextField("Currency Address", controller.MintERC20ContractAddress); + controller.MintERC20RecipientAddress = EditorGUILayout.TextField("Recipient Address", controller.MintERC20RecipientAddress); + controller.MintERC20Amount = EditorGUILayout.TextField("Amount", controller.MintERC20Amount); + GUILayout.Space(8); + if (GUILayout.Button("Mint CurrencyToken", ButtonStyle, GUILayout.Height(26))) + controller.MintERC20(); + break; + + case ContractType.NFTContract: + controller.SafeMintERC721ContractAddress = EditorGUILayout.TextField("NFT Contract Address", controller.SafeMintERC721ContractAddress); + controller.IsBatchMintERC721 = EditorGUILayout.Toggle("Batch Mint", controller.IsBatchMintERC721); + + GUILayout.Space(8); + + if (controller.IsBatchMintERC721) + { + int batchSize = controller.SafeMintERC721BatchRecipients?.Length ?? 0; + batchSize = EditorGUILayout.IntField("Batch Size", batchSize); + batchSize = Mathf.Max(batchSize, 0); + GUILayout.Space(6); + + var recipients = controller.SafeMintERC721BatchRecipients ?? new string[0]; + var tokenIds = controller.SafeMintERC721BatchTokenIds ?? new string[0]; + + if (recipients.Length != batchSize) + Array.Resize(ref recipients, batchSize); + if (tokenIds.Length != batchSize) + Array.Resize(ref tokenIds, batchSize); + + for (int i = 0; i < batchSize; i++) + { + EditorGUILayout.LabelField($"Mint {i + 1}", LabelBoldStyle); + recipients[i] = EditorGUILayout.TextField("Recipient", recipients[i]); + tokenIds[i] = EditorGUILayout.TextField("Token ID", tokenIds[i]); + GUILayout.Space(6); + } + + controller.SafeMintERC721BatchRecipients = recipients; + controller.SafeMintERC721BatchTokenIds = tokenIds; + + if (GUILayout.Button("Mint NFT Contract Batch", ButtonStyle, GUILayout.Height(26))) + controller.SafeMintBatchERC721(); + } + else + { + controller.SafeMintERC721Recipient = EditorGUILayout.TextField("Recipient Address", controller.SafeMintERC721Recipient); + controller.SafeMintERC721TokenId = EditorGUILayout.TextField("Token ID", controller.SafeMintERC721TokenId); + GUILayout.Space(8); + if (GUILayout.Button("Mint NFT Contract", ButtonStyle, GUILayout.Height(26))) + controller.SafeMintERC721(); + } + break; + + case ContractType.Web3GameItem: + controller.MintERC1155ContractAddress = EditorGUILayout.TextField("Item Address", controller.MintERC1155ContractAddress); + controller.IsBatchMintERC1155 = EditorGUILayout.Toggle("Batch Mint", controller.IsBatchMintERC1155); + GUILayout.Space(8); + + if (controller.IsBatchMintERC1155) + { + int batchSize = controller.MintERC1155BatchRecipients?.Length ?? 0; + batchSize = EditorGUILayout.IntField("Batch Size", batchSize); + batchSize = Mathf.Max(batchSize, 0); + GUILayout.Space(6); + + var recipients = controller.MintERC1155BatchRecipients ?? new string[0]; + var ids = controller.MintERC1155BatchIds ?? new string[0]; + var amounts = controller.MintERC1155BatchAmounts ?? new string[0]; + var datas = controller.MintERC1155BatchDatas ?? new string[0]; + + if (recipients.Length != batchSize) Array.Resize(ref recipients, batchSize); + if (ids.Length != batchSize) Array.Resize(ref ids, batchSize); + if (amounts.Length != batchSize) Array.Resize(ref amounts, batchSize); + if (datas.Length != batchSize) Array.Resize(ref datas, batchSize); + + for (int i = 0; i < batchSize; i++) + { + EditorGUILayout.LabelField($"Mint {i + 1}", LabelBoldStyle); + recipients[i] = EditorGUILayout.TextField("Recipient", recipients[i]); + ids[i] = EditorGUILayout.TextField("ID", ids[i]); + amounts[i] = EditorGUILayout.TextField("Amount", amounts[i]); + datas[i] = EditorGUILayout.TextField("Data", datas[i]); + GUILayout.Space(6); + } + + controller.MintERC1155BatchRecipients = recipients; + controller.MintERC1155BatchIds = ids; + controller.MintERC1155BatchAmounts = amounts; + controller.MintERC1155BatchDatas = datas; + + if (GUILayout.Button("Mint Web 3 Game Item Batch", ButtonStyle, GUILayout.Height(26))) + controller.MintERC1155Batch(); + } + else + { + controller.MintERC1155RecipientAddress = EditorGUILayout.TextField("Recipient Address", controller.MintERC1155RecipientAddress); + controller.MintERC1155Id = EditorGUILayout.TextField("ID", controller.MintERC1155Id); + controller.MintERC1155Amount = EditorGUILayout.TextField("Amount", controller.MintERC1155Amount); + controller.MintERC1155Data = EditorGUILayout.TextField("Data", controller.MintERC1155Data); + GUILayout.Space(8); + if (GUILayout.Button("Mint Web 3 Game Item", ButtonStyle, GUILayout.Height(26))) + controller.MintERC1155(); + } + break; + } + } } + #endregion + #region Generate SO + generateFoldout = EditorGUILayout.Foldout(generateFoldout, "Generate SO", true, FoldoutStyle); + if (generateFoldout) + { + using (new EditorGUILayout.VerticalScope(SectionBoxStyle)) + { + selectedGenerateType = (ContractType)EditorGUILayout.EnumPopup("Contract Type", selectedGenerateType); + GUILayout.Space(8); + + switch (selectedGenerateType) + { + case ContractType.CurrencyToken: + controller.soContractAddress = EditorGUILayout.TextField("Currency Address", controller.soContractAddress); + controller.soTokenDecimals = EditorGUILayout.IntField("Token Decimals", controller.soTokenDecimals); + GUILayout.Space(8); + + if (GUILayout.Button("Create Currency Token ScriptableObject", ButtonStyle, GUILayout.Height(26))) + { + var asset = CreateInstance(); + asset.contractAddress = controller.soContractAddress; + + string path = EditorUtility.SaveFilePanelInProject("Save ERC20 ScriptableObject", "NewERC20Scriptable", "asset", "Please enter a file name to save the asset to"); + if (!string.IsNullOrEmpty(path)) + { + AssetDatabase.CreateAsset(asset, path); + AssetDatabase.SaveAssets(); + EditorUtility.FocusProjectWindow(); + Selection.activeObject = asset; + } + } + break; - #endregion + case ContractType.NFTContract: + controller.soContractAddress = EditorGUILayout.TextField("Contract Address", controller.soContractAddress); + GUILayout.Space(8); - base.OnInspectorGUI(); + if (GUILayout.Button("Create NFT Contract ScriptableObject", ButtonStyle, GUILayout.Height(26))) + { + var asset = CreateInstance(); + asset.contractAddress = controller.soContractAddress; + + string path = EditorUtility.SaveFilePanelInProject("Save ERC721 ScriptableObject", "NewERC721Scriptable", "asset", "Please enter a file name to save the asset to"); + if (!string.IsNullOrEmpty(path)) + { + AssetDatabase.CreateAsset(asset, path); + AssetDatabase.SaveAssets(); + EditorUtility.FocusProjectWindow(); + Selection.activeObject = asset; + } + } + + break; + + case ContractType.Web3GameItem: + controller.soContractAddress = EditorGUILayout.TextField("Item Address", controller.soContractAddress); + controller.soSpecifyBurnAddress = EditorGUILayout.Toggle("Specify Burn Address", controller.soSpecifyBurnAddress); + + if (controller.soSpecifyBurnAddress) + { + controller.soContractBurnAddress = EditorGUILayout.TextField("Burn Address", controller.soContractBurnAddress); + + } + GUILayout.Space(8); + + if (GUILayout.Button("Create Web 3 Game Item ScriptableObject", ButtonStyle, GUILayout.Height(26))) + { + var asset = CreateInstance(); + asset.contractAddress = controller.soContractAddress; + asset.specifyBurnAddress = controller.soSpecifyBurnAddress; + + string path = EditorUtility.SaveFilePanelInProject("Save ERC1155 ScriptableObject", "NewERC1155Scriptable", "asset", "Please enter a file name to save the asset to"); + if (!string.IsNullOrEmpty(path)) + { + AssetDatabase.CreateAsset(asset, path); + AssetDatabase.SaveAssets(); + EditorUtility.FocusProjectWindow(); + Selection.activeObject = asset; + } + } + break; + + } + } + } + #endregion } -} \ No newline at end of file + + private Texture2D MakeTex(int width, int height, Color col) + { + Color[] pix = new Color[width * height]; + for (int i = 0; i < pix.Length; i++) pix[i] = col; + Texture2D result = new Texture2D(width, height); + result.SetPixels(pix); + result.Apply(); + return result; + } +} + +public enum ContractType +{ + CurrencyToken, + NFTContract, + Web3GameItem, +} + +public enum ContractRole +{ + Minter +} diff --git a/Assets/SidekickEditor/SidekickEditorController.cs b/Assets/SidekickEditor/SidekickEditorController.cs index 2d15f152..db72d80e 100644 --- a/Assets/SidekickEditor/SidekickEditorController.cs +++ b/Assets/SidekickEditor/SidekickEditorController.cs @@ -1,72 +1,396 @@ using UnityEditor; using UnityEngine; +using System.Text; using Sequence; using Sequence.Sidekick; - +using Sequence.Provider; public class SidekickEditorController : MonoBehaviour { private SequenceSidekickClient sidekick = new SequenceSidekickClient(Chain.TestnetArbitrumSepolia); + #region Sidekick Wallet + + public void GetWalletAddress() + { + EditorApplication.delayCall += async () => + { + try + { + string result = await sidekick.GetWalletAddress(); + Debug.Log(result); + } + catch (System.Exception ex) + { + Debug.LogError("Failed to recover sidekick wallet address: " + ex.Message); + } + }; + } + + #endregion + + #region Sidekick Contracts + + public void GetContracts() + { + EditorApplication.delayCall += async () => + { + try + { + string result = await sidekick.GetAllContracts(); + Debug.Log(result); + } + catch (System.Exception ex) + { + Debug.LogError("Failed to recover builder contracts: " + ex.Message); + } + }; + } + + #endregion + + #region Deploy + + #region Deploy ERC20 + + public string DeployERC20InitialOwner { get; set; } + public string DeployERC20Name { get; set; } + public string DeployERC20Symbol { get; set; } + + public async void DeployERC20() + { + + var payload = new DeployERC20Payload + { + initialOwner = DeployERC20InitialOwner, + name = DeployERC20Name, + symbol = DeployERC20Symbol + }; + + string jsonString = JsonUtility.ToJson(payload); + + Debug.Log("Deploying ERC20: " + jsonString); + + try + { + string result = await sidekick.DeployERC20(jsonString); + + DeployResult deployResult = JsonUtility.FromJson(result); + + if (!string.IsNullOrEmpty(deployResult.result.txHash)) + { + + var receipt = await new SequenceEthClient(sidekick.Chain).WaitForTransactionReceipt(deployResult.result.txHash); + + if (receipt != null) + { + string deployedAddress = ReceiptExtractor.ExtractFirstContractAddressExceptOwn(receipt, DeployERC20InitialOwner); + if (!string.IsNullOrEmpty(deployedAddress)) + { + Debug.Log($"Deployed contract address: {deployedAddress}"); + } + else + { + Debug.LogWarning("Could not extract deployed contract address from receipt."); + } + } + else + { + Debug.LogError("Failed to get transaction receipt."); + } + } + else + { + Debug.LogError($"Deployment error: {deployResult.result.error}"); + } + } + catch (System.Exception ex) + { + Debug.LogError("Deploy ERC20 failed: " + ex.Message); + } + } + + #endregion + + #region Deploy ERC721 + public string DeployERC721DefaultAdmin { get; set; } + public string DeployERC721Minter { get; set; } + public string DeployERC721Name { get; set; } + public string DeployERC721Symbol { get; set; } + + public async void DeployERC721() + { + var payload = new DeployERC721Payload + { + defaultAdmin = DeployERC721DefaultAdmin, + minter = DeployERC721Minter, + name = DeployERC721Name, + symbol = DeployERC721Symbol + }; + + string jsonString = JsonUtility.ToJson(payload); + + Debug.Log("Deploying ERC721: " + jsonString); + + try + { + string result = await sidekick.DeployERC721(jsonString); + + DeployResult deployResult = JsonUtility.FromJson(result); + + if (!string.IsNullOrEmpty(deployResult.result.txHash)) + { + + var receipt = await new SequenceEthClient(sidekick.Chain).WaitForTransactionReceipt(deployResult.result.txHash); + + if (receipt != null) + { + string deployedAddress = ReceiptExtractor.ExtractFirstContractAddressExceptOwn(receipt, DeployERC721DefaultAdmin); + if (!string.IsNullOrEmpty(deployedAddress)) + { + Debug.Log($"Deployed contract address: {deployedAddress}"); + } + else + { + Debug.LogWarning("Could not extract deployed contract address from receipt."); + } + } + else + { + Debug.LogError("Failed to get transaction receipt."); + } + } + else + { + Debug.LogError($"Deployment error: {deployResult.result.error}"); + } + } + catch (System.Exception ex) + { + Debug.LogError("Deploy ERC721 failed: " + ex.Message); + } + } + + #endregion + #region Deploy ERC1155 - public string deployDefaultAdmin { get; set; } - public string deployMinter { get; set; } - public string deployName { get; set; } + public string DeployDefaultAdmin { get; set; } + public string DeployMinter { get; set; } + public string DeployName { get; set; } - public async void DeployERC1155(string defaultAdmin, string minter, string name) + public async void DeployERC1155() { var deployPayload = new DeployERC1155Payload { - defaultAdmin = defaultAdmin, - minter = minter, - name = name + defaultAdmin = DeployDefaultAdmin, + minter = DeployMinter, + name = DeployName }; + string jsonString = JsonUtility.ToJson(deployPayload); - Debug.Log("Deploying ERC1155:" + jsonString); + Debug.Log("Deploying ERC1155: " + jsonString); + + try + { + string result = await sidekick.DeployERC1155(jsonString); + + DeployResult deployResult = JsonUtility.FromJson(result); + + if (!string.IsNullOrEmpty(deployResult.result.txHash)) + { + var receipt = await new SequenceEthClient(sidekick.Chain).WaitForTransactionReceipt(deployResult.result.txHash); + + if (receipt != null) + { + string deployedAddress = ReceiptExtractor.ExtractFirstContractAddressExceptOwn(receipt, DeployDefaultAdmin); + if (!string.IsNullOrEmpty(deployedAddress)) + { + Debug.Log($"Deployed contract address: {deployedAddress}"); + } + else + { + Debug.LogWarning("Could not extract deployed contract address from receipt."); + } + } + else + { + Debug.LogError("Failed to get transaction receipt."); + } + } + else + { + Debug.LogError($"Deployment error: {deployResult.result.error}"); + } + } + catch (System.Exception ex) + { + Debug.LogError("Deploy ERC1155 failed: " + ex.Message); + } + } + + #endregion + + #endregion + + #region Role + + public ContractRole SelectedContractRole { get; set; } + public string GrantRoleContractAddress { get; set; } + public string GrantRoleRole { get; set; } + public string GrantRoleAccount { get; set; } + + public void GrantERC1155Role() + { + var grantRolePayload = new GrantRolePayload + { + role = GrantRoleRole, + account = GrantRoleAccount + }; + + string jsonString = JsonUtility.ToJson(grantRolePayload); + + Debug.Log("Granting role ERC1155: " + jsonString); + + EditorApplication.delayCall += async () => + { + try + { + string result = await sidekick.GrantRoleERC1155(GrantRoleContractAddress, jsonString); + Debug.Log("Grant role result: " + result); + } + catch (System.Exception ex) + { + Debug.LogError("Grant ERC1155 role failed: " + ex.Message); + } + }; + } + + #endregion + + #region Mint + + #region MintERC20 + + public string MintERC20ContractAddress { get; set; } + public string MintERC20RecipientAddress { get; set; } + public string MintERC20Amount { get; set; } + + public void MintERC20() + { + var mintJson = new MintERC20Payload + { + to = MintERC20RecipientAddress, + amount = MintERC20Amount + }; + string jsonString = JsonUtility.ToJson(mintJson); + + Debug.Log("Minting ERC20: " + jsonString); EditorApplication.delayCall += async () => { try { - string result = await sidekick.DeployERC1155(sidekick.Chain.GetChainId(), jsonString); - Debug.Log("Deploy result: " + result); + string result = await sidekick.MintERC20(MintERC20ContractAddress, jsonString); + Debug.Log("Mint result: " + result); } catch (System.Exception ex) { - Debug.LogError("Deploy ERC1155 failed: " + ex.Message); + Debug.LogError("Mint ERC20 failed: " + ex.Message); } }; } #endregion + + #region Mint ERC721 + + public bool IsBatchMintERC721 { get; set; } = false; + public string SafeMintERC721ContractAddress { get; set; } + + public string SafeMintERC721Recipient { get; set; } + public string SafeMintERC721TokenId { get; set; } + + public async void SafeMintERC721() + { + var payload = new SafeMintERC721Payload + { + to = SafeMintERC721Recipient, + tokenId = SafeMintERC721TokenId + }; + string jsonString = JsonUtility.ToJson(payload); + + Debug.Log("Calling safeMint ERC721: " + jsonString); + + try + { + string result = await sidekick.SafeMintERC721(SafeMintERC721ContractAddress, jsonString); + Debug.Log("safeMint result: " + result); + } + catch (System.Exception ex) + { + Debug.LogError("safeMint ERC721 failed: " + ex.Message); + } + } + + public string[] SafeMintERC721BatchRecipients { get; set; } + public string[] SafeMintERC721BatchTokenIds { get; set; } + + public async void SafeMintBatchERC721() + { + var payload = new SafeMintBatchERC721Payload + { + recipients = SafeMintERC721BatchRecipients, + tokenIds = SafeMintERC721BatchTokenIds + }; + string jsonString = JsonUtility.ToJson(payload); + + Debug.Log("Calling safeMintBatch ERC721: " + jsonString); + + try + { + string result = await sidekick.SafeMintBatchERC721(SafeMintERC721ContractAddress, jsonString); + Debug.Log("safeMintBatch result: " + result); + } + catch (System.Exception ex) + { + Debug.LogError("safeMintBatch ERC721 failed: " + ex.Message); + } + } + + #endregion + #region Mint ERC1155 - [HideInInspector] public string MintContractAddress; - public string MintRecipientAddress { get; set; } - public string MintId { get; set; } - public string MintAmount { get; set; } - public string MintData { get; set; } + public bool IsBatchMintERC1155 { get; set; } = false; + + public string MintERC1155ContractAddress { get; set; } - public async void MintERC1155(string contractAddress, string recipient, string id, string amount, string data) + public string MintERC1155RecipientAddress { get; set; } + public string MintERC1155Id { get; set; } + public string MintERC1155Amount { get; set; } + public string MintERC1155Data { get; set; } + public void MintERC1155() { - var mintJson = new + var mintJson = new MintERC1155Payload { - recipient = recipient, - id = id, - amount = amount, - data = data + recipient = MintERC1155RecipientAddress, + id = MintERC1155Id, + amount = MintERC1155Amount, + data = ToHexString(MintERC1155Data) }; + string jsonString = JsonUtility.ToJson(mintJson); - Debug.Log(jsonString); + + Debug.Log("Minting ERC1155: " + jsonString); EditorApplication.delayCall += async () => { try { - string result = await sidekick.MintERC1155(sidekick.Chain.GetChainId(), contractAddress, jsonString); + string result = await sidekick.MintERC1155(MintERC1155ContractAddress, jsonString); Debug.Log("Mint result: " + result); } catch (System.Exception ex) @@ -75,10 +399,79 @@ public async void MintERC1155(string contractAddress, string recipient, string i } }; } + public string[] MintERC1155BatchRecipients { get; set; } = new string[0]; + public string[] MintERC1155BatchIds { get; set; } = new string[0]; + public string[] MintERC1155BatchAmounts { get; set; } = new string[0]; + public string[] MintERC1155BatchDatas { get; set; } = new string[0]; + + public void MintERC1155Batch() + { + string[] hexDatas = new string[MintERC1155BatchDatas.Length]; + + for (int i = 0; i < MintERC1155BatchDatas.Length; i++) + { + hexDatas[i] = ToHexString(MintERC1155BatchDatas[i]); + + } + + var mintJson = new MintERC1155BatchPayload + { + recipients = MintERC1155BatchRecipients, + ids = MintERC1155BatchIds, + amounts = MintERC1155BatchAmounts, + datas = hexDatas + }; + + string jsonString = JsonUtility.ToJson(mintJson); + Debug.Log("Minting ERC1155 Batch: " + jsonString); + + EditorApplication.delayCall += async () => + { + try + { + string result = await sidekick.MintBatchERC1155(MintERC1155ContractAddress, jsonString); + Debug.Log("Mint batch result: " + result); + } + catch (System.Exception ex) + { + Debug.LogError("Mint ERC1155 batch failed: " + ex.Message); + } + }; + } + + #endregion + + + #endregion + + + #region Create SO + + public string soContractAddress { get; set; } + public string soContractBurnAddress { get; set; } + public int soTokenDecimals { get; set; } + public bool soSpecifyBurnAddress { get; set; } #endregion + public string ToHexString(string input) + { + byte[] bytes = Encoding.UTF8.GetBytes(input); + StringBuilder hex = new StringBuilder("0x"); + + foreach (byte b in bytes) + { + hex.Append(b.ToString("x2")); + } + + return hex.ToString(); + } } + +#region Payloads + +#region Deploy + [System.Serializable] public class DeployERC1155Payload { @@ -86,3 +479,94 @@ public class DeployERC1155Payload public string minter; public string name; } + +[System.Serializable] +public class DeployERC20Payload +{ + public string initialOwner; + public string name; + public string symbol; +} + +[System.Serializable] +public class DeployERC721Payload +{ + public string defaultAdmin; + public string minter; + public string name; + public string symbol; +} + +#endregion + +#region Mint + +[System.Serializable] +public class MintERC20Payload +{ + public string to; + public string amount; +} + + +[System.Serializable] +public class SafeMintERC721Payload +{ + public string to; + public string tokenId; +} + +[System.Serializable] +public class SafeMintBatchERC721Payload +{ + public string[] recipients; + public string[] tokenIds; +} +[System.Serializable] +public class MintERC1155Payload +{ + public string recipient; + public string id; + public string amount; + public string data; +} + +[System.Serializable] +public class MintERC1155BatchPayload +{ + public string[] recipients; + public string[] ids; + public string[] amounts; + public string[] datas; +} + + +#endregion + +#region Role + +[System.Serializable] +public class GrantRolePayload +{ + public string role; + public string account; +} + +#endregion + +#endregion + + +[System.Serializable] +public class DeployResult +{ + public ResultData result; + + [System.Serializable] + public class ResultData + { + public string txHash; + public string txUrl; + public string error; + } +} diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Config/SidekickConfig.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/Config/SidekickConfig.cs new file mode 100644 index 00000000..39553e65 --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Config/SidekickConfig.cs @@ -0,0 +1,7 @@ +using UnityEngine; + +[CreateAssetMenu(fileName = "SidekickConfig", menuName = "ScriptableObjects/SidekickConfig")] +public class SidekickConfig : ScriptableObject +{ + public string path; +} \ No newline at end of file diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Config/SidekickConfig.cs.meta b/Packages/Sequence-Unity/Sequence/SequenceSDK/Config/SidekickConfig.cs.meta new file mode 100644 index 00000000..0e347ce4 --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Config/SidekickConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cc489fae0c88420439d1433f41fd641c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs index 351e49eb..23c7de47 100644 --- a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs @@ -9,11 +9,13 @@ namespace Sequence.Sidekick public class SequenceSidekickClient { private static readonly HttpClient client = new(); - private string baseUrl = "http://localhost:3000"; + private string baseUrl = "http://localhost:3000"; private string secretKey = "ultrasecretkey"; public Chain Chain; + private string ChainId => Chain.GetChainId(); + public SequenceSidekickClient() { } public SequenceSidekickClient(Chain chain) @@ -72,18 +74,17 @@ public async Task GetWalletAddress() { return await GetAsync("/sidekick/wallet-address"); } - #endregion #region Contract - public async Task ReadContract(string chainId, string address, string functionName, string json) + public async Task ReadContract(string address, string functionName, string json) { - return await PostAsync($"/read/contract/{chainId}/{address}/{functionName}", json); + return await PostAsync($"/read/contract/{ChainId}/{address}/{functionName}", json); } - public async Task WriteContract(string chainId, string address, string functionName, string json) + public async Task WriteContract(string address, string functionName, string json) { - return await PostAsync($"/write/contract/{chainId}/{address}/{functionName}", json); + return await PostAsync($"/write/contract/{ChainId}/{address}/{functionName}", json); } public async Task GetAllContracts() @@ -96,14 +97,14 @@ public async Task GetContract(string address) return await GetAsync($"/contract/get/{address}"); } - public async Task IsContractDeployed(string chainId, string address) + public async Task IsContractDeployed(string address) { - return await GetAsync($"/contract/isDeployed/{chainId}/{address}"); + return await GetAsync($"/contract/isDeployed/{ChainId}/{address}"); } - public async Task DeployContract(string chainId, string json) + public async Task DeployContract(string json) { - return await PostAsync($"/deploy/contract/{chainId}", json); + return await PostAsync($"/deploy/contract/{ChainId}", json); } public async Task ImportContractsFromBuilder(string projectId, string json) @@ -115,99 +116,92 @@ public async Task AddContract(string json) { return await PostAsync("/contract/add", json); } - #endregion #region ERC20 - public async Task TransferERC20(string chainId, string address, string json) - { - return await PostAsync($"/write/erc20/{chainId}/{address}/transfer", json); + public async Task TransferERC20(string address, string json) + { + return await PostAsync($"/write/erc20/{ChainId}/{address}/transfer", json); } - public async Task ApproveERC20(string chainId, string address, string json) + public async Task ApproveERC20(string address, string json) { - - return await PostAsync($"/write/erc20/{chainId}/{address}/approve", json); + return await PostAsync($"/write/erc20/{ChainId}/{address}/approve", json); } - public async Task MintERC20(string chainId, string address, string json) + public async Task MintERC20(string address, string json) { - return await PostAsync($"/write/erc20/{chainId}/{address}/mint", json); + return await PostAsync($"/write/erc20/{ChainId}/{address}/mint", json); } - public async Task TransferFromERC20(string chainId, string address, string json) + public async Task TransferFromERC20(string address, string json) { - return await PostAsync($"/write/erc20/{chainId}/{address}/transferFrom", json); + return await PostAsync($"/write/erc20/{ChainId}/{address}/transferFrom", json); } - public async Task DeployERC20(string chainId, string json) + public async Task DeployERC20(string json) { - return await PostAsync($"/deploy/erc20/{chainId}", json); + return await PostAsync($"/deploy/erc20/{ChainId}", json); } - #endregion #region ERC721 - - public async Task SafeMintERC721(string chainId, string address, string json) + public async Task SafeMintERC721(string address, string json) { - return await PostAsync($"/write/erc721/{chainId}/{address}/safeMint", json); + return await PostAsync($"/write/erc721/{ChainId}/{address}/safeMint", json); } - public async Task SafeMintBatchERC721(string chainId, string address, string json) + public async Task SafeMintBatchERC721(string address, string json) { - return await PostAsync($"/write/erc721/{chainId}/{address}/safeMintBatch", json); + return await PostAsync($"/write/erc721/{ChainId}/{address}/safeMintBatch", json); } - public async Task BalanceOfERC721(string chainId, string address) + public async Task BalanceOfERC721(string address) { - return await GetAsync($"/read/erc721/{chainId}/{address}/balanceOf"); + return await GetAsync($"/read/erc721/{ChainId}/{address}/balanceOf"); } - public async Task DeployERC721(string chainId, string json) + public async Task DeployERC721(string json) { - return await PostAsync($"/deploy/erc721/{chainId}", json); + return await PostAsync($"/deploy/erc721/{ChainId}", json); } - #endregion #region ERC1155 - - public async Task MintERC1155(string chainId, string address, string json) + public async Task MintERC1155(string address, string json) { - return await PostAsync($"/write/erc1155/{chainId}/{address}/mint", json); + return await PostAsync($"/write/erc1155/{ChainId}/{address}/mint", json); } - public async Task MintBatchERC1155(string chainId, string address, string json) + public async Task MintBatchERC1155(string address, string json) { - return await PostAsync($"/write/erc1155/{chainId}/{address}/mintBatch", json); + return await PostAsync($"/write/erc1155/{ChainId}/{address}/mintBatch", json); } - public async Task GrantRoleERC1155(string chainId, string address, string json) + public async Task GrantRoleERC1155(string address, string json) { - return await PostAsync($"/write/erc1155/{chainId}/{address}/grantRole", json); + return await PostAsync($"/write/erc1155/{ChainId}/{address}/grantRole", json); } - public async Task HasRoleERC1155(string chainId, string address) + public async Task HasRoleERC1155(string address) { - return await GetAsync($"/read/erc1155/{chainId}/{address}/hasRole"); + return await GetAsync($"/read/erc1155/{ChainId}/{address}/hasRole"); } - public async Task MinterRoleERC1155(string chainId, string address) + public async Task MinterRoleERC1155(string address) { - return await GetAsync($"/read/erc1155/{chainId}/{address}/minterRole"); + return await GetAsync($"/read/erc1155/{ChainId}/{address}/minterRole"); } - public async Task BalanceOfERC1155(string chainId, string address) + public async Task BalanceOfERC1155(string address) { - return await GetAsync($"/read/erc1155/{chainId}/{address}/balanceOf"); + return await GetAsync($"/read/erc1155/{ChainId}/{address}/balanceOf"); } - public async Task DeployERC1155(string chainId, string json) + public async Task DeployERC1155(string json) { - return await PostAsync($"/deploy/erc1155/{chainId}", json); + return await PostAsync($"/deploy/erc1155/{ChainId}", json); } - #endregion #region Transactions @@ -220,7 +214,6 @@ public async Task GetTransaction(string txHash) { return await GetAsync($"/transactions/{txHash}"); } - #endregion #region Webhooks @@ -236,25 +229,24 @@ public async Task RemoveWebhook(string json) public async Task RemoveAllWebhooks() { - return await PostAsync("/webhook/removeAll", ""); + return await PostAsync("/webhook/removeAll", ""); } public async Task GetAllWebhooks() { - return await GetAsync("/webhook/getAll"); + return await GetAsync("/webhook/getAll"); } - #endregion #region Jobs - public async Task StartERC20RewardsJob(string chainId, string address, string json) + public async Task StartERC20RewardsJob(string address, string json) { - return await PostAsync($"/jobs/erc20/rewards/{chainId}/{address}/start", json); + return await PostAsync($"/jobs/erc20/rewards/{ChainId}/{address}/start", json); } - public async Task StopERC20RewardsJob(string chainId, string address, string json) + public async Task StopERC20RewardsJob(string address, string json) { - return await PostAsync($"/jobs/erc20/rewards/{chainId}/{address}/stop", json); + return await PostAsync($"/jobs/erc20/rewards/{ChainId}/{address}/stop", json); } public async Task GetAllJobs() @@ -271,7 +263,6 @@ public async Task CleanJobs(string json) { return await PostAsync("/jobs/clean", json); } - #endregion } } diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects.meta b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects.meta new file mode 100644 index 00000000..67b88267 --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 404ebe9c6cb21d846aa8ed133114c6d8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC1155Scriptable.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC1155Scriptable.cs new file mode 100644 index 00000000..fdc0e916 --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC1155Scriptable.cs @@ -0,0 +1,27 @@ +using UnityEngine; +using Sequence.Contracts; + +[CreateAssetMenu(fileName = "ERC1155ContractData", menuName = "Sequence/ERC1155 Contract")] +public class ERC1155Scriptable : ScriptableObject +{ + public string contractAddress; + public bool specifyBurnAddress; + + public GameObject linkedGameObject; + + private ERC1155 _erc1155; + + + public ERC1155 GetContract() + { + if (_erc1155 == null) + { + if (specifyBurnAddress) + _erc1155 = new ERC1155(contractAddress, specifyBurnAddress); + else + _erc1155 = new ERC1155(contractAddress); + + } + return _erc1155; + } +} diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC1155Scriptable.cs.meta b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC1155Scriptable.cs.meta new file mode 100644 index 00000000..9aeaf163 --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC1155Scriptable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f43439d1f99de164fb5b87ee45ff3e5c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC20Scriptable.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC20Scriptable.cs new file mode 100644 index 00000000..4f88b984 --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC20Scriptable.cs @@ -0,0 +1,21 @@ +using UnityEngine; +using Sequence.Contracts; + +[CreateAssetMenu(fileName = "ERC20ContractData", menuName = "Sequence/ERC20 Contract")] +public class ERC20Scriptable : ScriptableObject +{ + public string contractAddress; + + public GameObject linkedGameObject; + + private ERC20 _erc20; + + public ERC20 GetContract() + { + if (_erc20 == null) + { + _erc20 = new ERC20(contractAddress); + } + return _erc20; + } +} diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC20Scriptable.cs.meta b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC20Scriptable.cs.meta new file mode 100644 index 00000000..a8f78637 --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC20Scriptable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5cea2bf24d028f846ab53bacf860010b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC721Scriptable.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC721Scriptable.cs new file mode 100644 index 00000000..b14e33a2 --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC721Scriptable.cs @@ -0,0 +1,21 @@ +using UnityEngine; +using Sequence.Contracts; + +[CreateAssetMenu(fileName = "ERC721ContractData", menuName = "Sequence/ERC721 Contract")] +public class ERC721Scriptable : ScriptableObject +{ + public string contractAddress; + + public GameObject linkedGameObject; + + private ERC721 _erc721; + + public ERC721 GetContract() + { + if (_erc721 == null) + { + _erc721 = new ERC721(contractAddress); + } + return _erc721; + } +} diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC721Scriptable.cs.meta b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC721Scriptable.cs.meta new file mode 100644 index 00000000..2b8423be --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/ScriptableObjects/ERC721Scriptable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fc72839ff10fc4d4fabd2d2d7bf77f5c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 9f4ae8a16442dd36b8990ad16bf7eed0b1726e6a Mon Sep 17 00:00:00 2001 From: caballoninja Date: Thu, 12 Jun 2025 12:24:05 -0300 Subject: [PATCH 4/4] Reviewed names, namespaces, asmdefs Fixes to scripts locations --- Assets/NewToken.asset | 17 - .../SideKick/Tests/SideKickWalletTests.cs | 39 -- .../SideKick/Tests/SidekickERC1155Tests.cs | 83 --- .../SideKick/Tests.meta => Sidekick.meta} | 2 +- .../Sidekick/SideKickWalletTests.cs | 37 ++ .../SideKickWalletTests.cs.meta | 0 .../Sidekick/SidekickERC1155Tests.cs | 81 +++ .../SidekickERC1155Tests.cs.meta | 0 .../SequenceSDK/Sidekick/SidekickTests.asmdef | 23 + .../Sidekick/SidekickTests.asmdef.meta} | 5 +- Assets/SidekickEditor/SidekickEditor.cs | 384 ------------ .../SidekickEditorController.cs | 572 ----------------- .../Sequence-Unity/Editor/Sidekick.meta | 2 +- .../Editor/Sidekick}/SidekickDockerUtility.cs | 73 ++- .../Sidekick}/SidekickDockerUtility.cs.meta | 0 .../Editor/Sidekick/SidekickEditor.asmdef | 22 + .../Sidekick/SidekickEditor.asmdef.meta | 7 + .../Editor/Sidekick/SidekickEditor.cs | 376 +++++++++++ .../Editor/Sidekick}/SidekickEditor.cs.meta | 0 .../SequenceSDK/Config/SidekickConfig.cs | 6 +- .../EmbeddedWallet/SequenceSidekickClient.cs | 9 +- .../SequenceSidekickClient.cs.meta | 2 +- .../DeployedContractAddressExtractor.cs | 4 +- .../DeployedContractAddressExtractor.cs.meta | 0 .../Sequence/SequenceSDK/Sidekick.meta | 2 +- .../Sidekick/SequenceSidekick.asmdef | 17 + .../Sidekick/SequenceSidekick.asmdef.meta | 7 + .../Sidekick/SidekickEditorController.cs | 588 ++++++++++++++++++ .../SidekickEditorController.cs.meta | 0 29 files changed, 1220 insertions(+), 1138 deletions(-) delete mode 100644 Assets/NewToken.asset delete mode 100644 Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs delete mode 100644 Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs rename Assets/SequenceSDK/{Marketplace/SideKick/Tests.meta => Sidekick.meta} (77%) create mode 100644 Assets/SequenceSDK/Sidekick/SideKickWalletTests.cs rename Assets/SequenceSDK/{Marketplace/SideKick/Tests => Sidekick}/SideKickWalletTests.cs.meta (100%) create mode 100644 Assets/SequenceSDK/Sidekick/SidekickERC1155Tests.cs rename Assets/SequenceSDK/{Marketplace/SideKick/Tests => Sidekick}/SidekickERC1155Tests.cs.meta (100%) create mode 100644 Assets/SequenceSDK/Sidekick/SidekickTests.asmdef rename Assets/{NewToken.asset.meta => SequenceSDK/Sidekick/SidekickTests.asmdef.meta} (52%) delete mode 100644 Assets/SidekickEditor/SidekickEditor.cs delete mode 100644 Assets/SidekickEditor/SidekickEditorController.cs rename Assets/SidekickEditor.meta => Packages/Sequence-Unity/Editor/Sidekick.meta (77%) rename {Assets/Editor => Packages/Sequence-Unity/Editor/Sidekick}/SidekickDockerUtility.cs (71%) rename {Assets/Editor => Packages/Sequence-Unity/Editor/Sidekick}/SidekickDockerUtility.cs.meta (100%) create mode 100644 Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.asmdef create mode 100644 Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.asmdef.meta create mode 100644 Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.cs rename {Assets/SidekickEditor => Packages/Sequence-Unity/Editor/Sidekick}/SidekickEditor.cs.meta (100%) rename {Assets => Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract}/DeployedContractAddressExtractor.cs (91%) rename {Assets => Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract}/DeployedContractAddressExtractor.cs.meta (100%) rename Assets/SequenceSDK/Marketplace/SideKick.meta => Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick.meta (77%) create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SequenceSidekick.asmdef create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SequenceSidekick.asmdef.meta create mode 100644 Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SidekickEditorController.cs rename {Assets/SidekickEditor => Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick}/SidekickEditorController.cs.meta (100%) diff --git a/Assets/NewToken.asset b/Assets/NewToken.asset deleted file mode 100644 index 5c71e260..00000000 --- a/Assets/NewToken.asset +++ /dev/null @@ -1,17 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f43439d1f99de164fb5b87ee45ff3e5c, type: 3} - m_Name: NewToken - m_EditorClassIdentifier: - contractAddress: 0x5f6e8810da77cb4762bfa5bdd2f6993bc9cd72a1 - specifyBurnAddress: 0 - linkedGameObject: {fileID: 0} diff --git a/Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs b/Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs deleted file mode 100644 index 66dba143..00000000 --- a/Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Threading.Tasks; -using NUnit.Framework; -using UnityEngine; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Sequence.Sidekick -{ - public class SequenceSidekickTests - { - SequenceSidekickClient sidekick; - string chainId; - - [SetUp] - public void Setup() - { - sidekick = new SequenceSidekickClient(Chain.TestnetArbitrumSepolia); - chainId = sidekick.Chain.GetChainId(); - - } - - [Test] - public async Task TestGetWalletAddress() - { - try - { - var sidekick = new SequenceSidekickClient(); - string walletAddress = await sidekick.GetWalletAddress(); - Assert.IsNotNull(walletAddress); - } - catch (Exception e) - { - Assert.Fail("Expected no exception, but got: " + e.Message); - } - } - - } -} \ No newline at end of file diff --git a/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs b/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs deleted file mode 100644 index 63125f2b..00000000 --- a/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Threading.Tasks; -using NUnit.Framework; -using UnityEngine; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Sequence.Sidekick -{ - public class SidekickERC1155MintTest - { - private SequenceSidekickClient sidekick; - private string chainId; - private string walletAddress; - - [SetUp] - public void Setup() - { - sidekick = new SequenceSidekickClient(Chain.TestnetArbitrumSepolia); - chainId = sidekick.Chain.GetChainId(); - } - - - [Test] - public async Task DeployERC1155() - { - try - { - walletAddress = await sidekick.GetWalletAddress(); - string recipientAddress = JObject.Parse(walletAddress)["address"]?.ToString(); - - var deployBody = new - { - defaultAdmin = recipientAddress, - minter = recipientAddress, - name = "MYTESTERC1155" - }; - - - string deployJson = JsonConvert.SerializeObject(deployBody); - - string deployResult = await sidekick.DeployERC1155(deployJson); - - Debug.Log("Deploy result: " + deployResult); - Assert.IsNotNull(deployResult, "Deploy result must not be null"); - } - catch (Exception e) - { - Assert.Fail("ERC1155 deploy flow failed: " + e.Message); - } - } - - - [Test] - public async Task MintERC1155() - { - try - { - walletAddress = await sidekick.GetWalletAddress(); - - string recipientAddress = JObject.Parse(walletAddress)["address"]?.ToString(); - - var mintBody = new - { - recipient = recipientAddress, - id = "0", - amount = "1", - data = "0x00" - }; - string mintJson = JsonConvert.SerializeObject(mintBody); - string mintResult = await sidekick.MintERC1155("0x63c12baa017b2bcb6855d83506500edcac423c3c", mintJson); - - Debug.Log("Mint result: " + mintResult); - - Assert.IsNotNull(mintResult, "Mint result must not be null"); - } - catch (Exception e) - { - Assert.Fail("ERC1155 flow failed: " + e.Message); - } - } - } -} \ No newline at end of file diff --git a/Assets/SequenceSDK/Marketplace/SideKick/Tests.meta b/Assets/SequenceSDK/Sidekick.meta similarity index 77% rename from Assets/SequenceSDK/Marketplace/SideKick/Tests.meta rename to Assets/SequenceSDK/Sidekick.meta index a4a048dd..d6e4fccf 100644 --- a/Assets/SequenceSDK/Marketplace/SideKick/Tests.meta +++ b/Assets/SequenceSDK/Sidekick.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 0241586cbfa27734f92fba37314ed60a +guid: 001fe241a79c272428e10da40e12c5a4 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/SequenceSDK/Sidekick/SideKickWalletTests.cs b/Assets/SequenceSDK/Sidekick/SideKickWalletTests.cs new file mode 100644 index 00000000..fe9206cb --- /dev/null +++ b/Assets/SequenceSDK/Sidekick/SideKickWalletTests.cs @@ -0,0 +1,37 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using Newtonsoft.Json.Linq; +using Sequence; +using Sequence.EmbeddedWallet; +public class SequenceSidekickTests +{ + SequenceSidekickClient sidekick; + string chainId; + + [SetUp] + public void Setup() + { + sidekick = new SequenceSidekickClient(Chain.TestnetArbitrumSepolia); + chainId = sidekick.Chain.GetChainId(); + + } + + [Test] + public async Task TestGetWalletAddress() + { + try + { + var sidekick = new SequenceSidekickClient(); + string response = await sidekick.GetWalletAddress(); + Assert.IsNotNull(response); + var json = JObject.Parse(response); + Assert.IsTrue(json.ContainsKey("walletAddress")); + } + catch (Exception e) + { + Assert.Fail("Expected no exception, but got: " + e.Message); + } + } + +} diff --git a/Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs.meta b/Assets/SequenceSDK/Sidekick/SideKickWalletTests.cs.meta similarity index 100% rename from Assets/SequenceSDK/Marketplace/SideKick/Tests/SideKickWalletTests.cs.meta rename to Assets/SequenceSDK/Sidekick/SideKickWalletTests.cs.meta diff --git a/Assets/SequenceSDK/Sidekick/SidekickERC1155Tests.cs b/Assets/SequenceSDK/Sidekick/SidekickERC1155Tests.cs new file mode 100644 index 00000000..741c4410 --- /dev/null +++ b/Assets/SequenceSDK/Sidekick/SidekickERC1155Tests.cs @@ -0,0 +1,81 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using UnityEngine; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Sequence.EmbeddedWallet; +using Sequence; +public class SidekickERC1155MintTest +{ + private SequenceSidekickClient sidekick; + private string chainId; + private string walletAddress; + + [SetUp] + public void Setup() + { + sidekick = new SequenceSidekickClient(Chain.TestnetArbitrumSepolia); + chainId = sidekick.Chain.GetChainId(); + } + + + [Test] + public async Task DeployERC1155() + { + try + { + walletAddress = await sidekick.GetWalletAddress(); + string recipientAddress = JObject.Parse(walletAddress)["address"]?.ToString(); + + var deployBody = new + { + defaultAdmin = recipientAddress, + minter = recipientAddress, + name = "MYTESTERC1155" + }; + + + string deployJson = JsonConvert.SerializeObject(deployBody); + + string deployResult = await sidekick.DeployERC1155(deployJson); + + Debug.Log("Deploy result: " + deployResult); + Assert.IsNotNull(deployResult, "Deploy result must not be null"); + } + catch (Exception e) + { + Assert.Fail("ERC1155 deploy flow failed: " + e.Message); + } + } + + + [Test] + public async Task MintERC1155() + { + try + { + walletAddress = await sidekick.GetWalletAddress(); + + string recipientAddress = JObject.Parse(walletAddress)["address"]?.ToString(); + + var mintBody = new + { + recipient = recipientAddress, + id = "0", + amount = "1", + data = "0x00" + }; + string mintJson = JsonConvert.SerializeObject(mintBody); + string mintResult = await sidekick.MintERC1155("0x63c12baa017b2bcb6855d83506500edcac423c3c", mintJson); + + Debug.Log("Mint result: " + mintResult); + + Assert.IsNotNull(mintResult, "Mint result must not be null"); + } + catch (Exception e) + { + Assert.Fail("ERC1155 flow failed: " + e.Message); + } + } +} diff --git a/Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs.meta b/Assets/SequenceSDK/Sidekick/SidekickERC1155Tests.cs.meta similarity index 100% rename from Assets/SequenceSDK/Marketplace/SideKick/Tests/SidekickERC1155Tests.cs.meta rename to Assets/SequenceSDK/Sidekick/SidekickERC1155Tests.cs.meta diff --git a/Assets/SequenceSDK/Sidekick/SidekickTests.asmdef b/Assets/SequenceSDK/Sidekick/SidekickTests.asmdef new file mode 100644 index 00000000..18a98a1b --- /dev/null +++ b/Assets/SequenceSDK/Sidekick/SidekickTests.asmdef @@ -0,0 +1,23 @@ +{ + "name": "SidekickTests", + "rootNamespace": "", + "references": [ + "GUID:4e0a798abbda240658187632ae443a67", + "GUID:f7fd4ba36aabd1d499450c174865e70b", + "GUID:0acc523941302664db1f4e527237feb3", + "GUID:27619889b8ba8c24980f49ee34dbb44a" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/NewToken.asset.meta b/Assets/SequenceSDK/Sidekick/SidekickTests.asmdef.meta similarity index 52% rename from Assets/NewToken.asset.meta rename to Assets/SequenceSDK/Sidekick/SidekickTests.asmdef.meta index 133e29c4..cadef0fb 100644 --- a/Assets/NewToken.asset.meta +++ b/Assets/SequenceSDK/Sidekick/SidekickTests.asmdef.meta @@ -1,8 +1,7 @@ fileFormatVersion: 2 -guid: 42986f857e82b284886ac8a43d483ab3 -NativeFormatImporter: +guid: a79d7c2264f7f5f46a4838d49aa6c43a +AssemblyDefinitionImporter: externalObjects: {} - mainObjectFileID: 11400000 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/SidekickEditor/SidekickEditor.cs b/Assets/SidekickEditor/SidekickEditor.cs deleted file mode 100644 index 1e128949..00000000 --- a/Assets/SidekickEditor/SidekickEditor.cs +++ /dev/null @@ -1,384 +0,0 @@ -using UnityEditor; -using UnityEngine; -using System; - -[CustomEditor(typeof(SidekickEditorController))] -public class SidekickEditor : Editor -{ - bool deployFoldout = true; - bool mintFoldout = true; - bool generateFoldout = true; - bool grantRoleFoldout = true; - - ContractType selectedDeployType; - ContractType selectedMintType; - ContractType selectedGenerateType; - - GUIStyle HeaderStyle => new GUIStyle(EditorStyles.label) - { - fontStyle = FontStyle.Bold, - fontSize = 16, - normal = { textColor = new Color(0.9f, 0.9f, 0.9f) } - }; - - GUIStyle FoldoutStyle => new GUIStyle(EditorStyles.foldout) - { - fontStyle = FontStyle.Bold, - fontSize = 14, - normal = { textColor = new Color(0.8f, 0.8f, 0.8f) }, - hover = { textColor = Color.white }, - active = { textColor = Color.white } - }; - - GUIStyle SectionBoxStyle - { - get - { - var style = new GUIStyle(GUI.skin.box); - style.normal.background = MakeTex(2, 2, new Color(0.15f, 0.15f, 0.15f, 0.7f)); - style.margin = new RectOffset(0, 0, 5, 10); - style.padding = new RectOffset(10, 10, 10, 10); - return style; - } - } - GUIStyle ButtonStyle - { - get - { - var style = new GUIStyle(GUI.skin.button) - { - fontStyle = FontStyle.Bold, - fontSize = 13 - }; - - style.normal.textColor = Color.white; - style.hover.textColor = Color.white; - - return style; - } - } - GUIStyle LabelBoldStyle => new GUIStyle(EditorStyles.label) - { - fontStyle = FontStyle.Bold, - fontSize = 12, - normal = { textColor = Color.white } - }; - - public override void OnInspectorGUI() - { - var controller = (SidekickEditorController)target; - - EditorGUILayout.Space(8); - EditorGUILayout.LabelField("Sidekick Wallet", HeaderStyle); - - GUILayout.Space(6); - if (GUILayout.Button("Get Wallet Address", ButtonStyle, GUILayout.Height(28))) - controller.GetWalletAddress(); - - //GUILayout.Space(6); - //if (GUILayout.Button("Get Contracts", ButtonStyle, GUILayout.Height(28))) - // controller.GetContracts(); - - EditorGUILayout.Space(14); - - #region Deploy - deployFoldout = EditorGUILayout.Foldout(deployFoldout, "Deploy", true, FoldoutStyle); - if (deployFoldout) - { - using (new EditorGUILayout.VerticalScope(SectionBoxStyle)) - { - selectedDeployType = (ContractType)EditorGUILayout.EnumPopup("Contract Type", selectedDeployType); - - EditorGUILayout.Space(); - - switch (selectedDeployType) - { - case ContractType.CurrencyToken: - controller.DeployERC20InitialOwner = EditorGUILayout.TextField("Initial Owner", controller.DeployERC20InitialOwner); - controller.DeployERC20Name = EditorGUILayout.TextField("Name", controller.DeployERC20Name); - controller.DeployERC20Symbol = EditorGUILayout.TextField("Symbol", controller.DeployERC20Symbol); - GUILayout.Space(8); - if (GUILayout.Button("Deploy Currency Token", ButtonStyle, GUILayout.Height(26))) - controller.DeployERC20(); - break; - - case ContractType.NFTContract: - controller.DeployERC721DefaultAdmin = EditorGUILayout.TextField("Default Admin", controller.DeployERC721DefaultAdmin); - controller.DeployERC721Minter = EditorGUILayout.TextField("Minter", controller.DeployERC721Minter); - controller.DeployERC721Name = EditorGUILayout.TextField("Name", controller.DeployERC721Name); - controller.DeployERC721Symbol = EditorGUILayout.TextField("Symbol", controller.DeployERC721Symbol); - GUILayout.Space(8); - if (GUILayout.Button("Deploy NFT Contract", ButtonStyle, GUILayout.Height(26))) - controller.DeployERC721(); - break; - - case ContractType.Web3GameItem: - controller.DeployDefaultAdmin = EditorGUILayout.TextField("Default Admin", controller.DeployDefaultAdmin); - controller.DeployMinter = EditorGUILayout.TextField("Minter", controller.DeployMinter); - controller.DeployName = EditorGUILayout.TextField("Name", controller.DeployName); - GUILayout.Space(8); - if (GUILayout.Button("Deploy Web 3 Game Item", ButtonStyle, GUILayout.Height(26))) - controller.DeployERC1155(); - break; - } - } - } - #endregion - - #region Grant Role - grantRoleFoldout = EditorGUILayout.Foldout(grantRoleFoldout, "Grant Role", true, FoldoutStyle); - if (grantRoleFoldout) - { - using (new EditorGUILayout.VerticalScope(SectionBoxStyle)) - { - controller.SelectedContractRole = (ContractRole)EditorGUILayout.EnumPopup("Role", controller.SelectedContractRole); - - switch (controller.SelectedContractRole) - { - case ContractRole.Minter: - controller.GrantRoleRole = "0xdfd8f10cabf255ee49ecf3db8b4502eea7eac26c270f6e5f0f28506f6f3fbb55"; - break; - default: - throw new ArgumentOutOfRangeException(nameof(controller.SelectedContractRole), "Unsupported role"); - } - - controller.GrantRoleContractAddress = EditorGUILayout.TextField("Contract Address", controller.GrantRoleContractAddress); - controller.GrantRoleAccount = EditorGUILayout.TextField("Account Address", controller.GrantRoleAccount); - - GUILayout.Space(8); - - if (GUILayout.Button("Grant Role", ButtonStyle, GUILayout.Height(26))) - controller.GrantERC1155Role(); - } - } - #endregion - - #region Mint - mintFoldout = EditorGUILayout.Foldout(mintFoldout, "Mint", true, FoldoutStyle); - if (mintFoldout) - { - using (new EditorGUILayout.VerticalScope(SectionBoxStyle)) - { - selectedMintType = (ContractType)EditorGUILayout.EnumPopup("Item Type", selectedMintType); - GUILayout.Space(6); - - switch (selectedMintType) - { - case ContractType.CurrencyToken: - controller.MintERC20ContractAddress = EditorGUILayout.TextField("Currency Address", controller.MintERC20ContractAddress); - controller.MintERC20RecipientAddress = EditorGUILayout.TextField("Recipient Address", controller.MintERC20RecipientAddress); - controller.MintERC20Amount = EditorGUILayout.TextField("Amount", controller.MintERC20Amount); - GUILayout.Space(8); - if (GUILayout.Button("Mint CurrencyToken", ButtonStyle, GUILayout.Height(26))) - controller.MintERC20(); - break; - - case ContractType.NFTContract: - controller.SafeMintERC721ContractAddress = EditorGUILayout.TextField("NFT Contract Address", controller.SafeMintERC721ContractAddress); - controller.IsBatchMintERC721 = EditorGUILayout.Toggle("Batch Mint", controller.IsBatchMintERC721); - - GUILayout.Space(8); - - if (controller.IsBatchMintERC721) - { - int batchSize = controller.SafeMintERC721BatchRecipients?.Length ?? 0; - batchSize = EditorGUILayout.IntField("Batch Size", batchSize); - batchSize = Mathf.Max(batchSize, 0); - GUILayout.Space(6); - - var recipients = controller.SafeMintERC721BatchRecipients ?? new string[0]; - var tokenIds = controller.SafeMintERC721BatchTokenIds ?? new string[0]; - - if (recipients.Length != batchSize) - Array.Resize(ref recipients, batchSize); - if (tokenIds.Length != batchSize) - Array.Resize(ref tokenIds, batchSize); - - for (int i = 0; i < batchSize; i++) - { - EditorGUILayout.LabelField($"Mint {i + 1}", LabelBoldStyle); - recipients[i] = EditorGUILayout.TextField("Recipient", recipients[i]); - tokenIds[i] = EditorGUILayout.TextField("Token ID", tokenIds[i]); - GUILayout.Space(6); - } - - controller.SafeMintERC721BatchRecipients = recipients; - controller.SafeMintERC721BatchTokenIds = tokenIds; - - if (GUILayout.Button("Mint NFT Contract Batch", ButtonStyle, GUILayout.Height(26))) - controller.SafeMintBatchERC721(); - } - else - { - controller.SafeMintERC721Recipient = EditorGUILayout.TextField("Recipient Address", controller.SafeMintERC721Recipient); - controller.SafeMintERC721TokenId = EditorGUILayout.TextField("Token ID", controller.SafeMintERC721TokenId); - GUILayout.Space(8); - if (GUILayout.Button("Mint NFT Contract", ButtonStyle, GUILayout.Height(26))) - controller.SafeMintERC721(); - } - break; - - case ContractType.Web3GameItem: - controller.MintERC1155ContractAddress = EditorGUILayout.TextField("Item Address", controller.MintERC1155ContractAddress); - controller.IsBatchMintERC1155 = EditorGUILayout.Toggle("Batch Mint", controller.IsBatchMintERC1155); - GUILayout.Space(8); - - if (controller.IsBatchMintERC1155) - { - int batchSize = controller.MintERC1155BatchRecipients?.Length ?? 0; - batchSize = EditorGUILayout.IntField("Batch Size", batchSize); - batchSize = Mathf.Max(batchSize, 0); - GUILayout.Space(6); - - var recipients = controller.MintERC1155BatchRecipients ?? new string[0]; - var ids = controller.MintERC1155BatchIds ?? new string[0]; - var amounts = controller.MintERC1155BatchAmounts ?? new string[0]; - var datas = controller.MintERC1155BatchDatas ?? new string[0]; - - if (recipients.Length != batchSize) Array.Resize(ref recipients, batchSize); - if (ids.Length != batchSize) Array.Resize(ref ids, batchSize); - if (amounts.Length != batchSize) Array.Resize(ref amounts, batchSize); - if (datas.Length != batchSize) Array.Resize(ref datas, batchSize); - - for (int i = 0; i < batchSize; i++) - { - EditorGUILayout.LabelField($"Mint {i + 1}", LabelBoldStyle); - recipients[i] = EditorGUILayout.TextField("Recipient", recipients[i]); - ids[i] = EditorGUILayout.TextField("ID", ids[i]); - amounts[i] = EditorGUILayout.TextField("Amount", amounts[i]); - datas[i] = EditorGUILayout.TextField("Data", datas[i]); - GUILayout.Space(6); - } - - controller.MintERC1155BatchRecipients = recipients; - controller.MintERC1155BatchIds = ids; - controller.MintERC1155BatchAmounts = amounts; - controller.MintERC1155BatchDatas = datas; - - if (GUILayout.Button("Mint Web 3 Game Item Batch", ButtonStyle, GUILayout.Height(26))) - controller.MintERC1155Batch(); - } - else - { - controller.MintERC1155RecipientAddress = EditorGUILayout.TextField("Recipient Address", controller.MintERC1155RecipientAddress); - controller.MintERC1155Id = EditorGUILayout.TextField("ID", controller.MintERC1155Id); - controller.MintERC1155Amount = EditorGUILayout.TextField("Amount", controller.MintERC1155Amount); - controller.MintERC1155Data = EditorGUILayout.TextField("Data", controller.MintERC1155Data); - GUILayout.Space(8); - if (GUILayout.Button("Mint Web 3 Game Item", ButtonStyle, GUILayout.Height(26))) - controller.MintERC1155(); - } - break; - } - } - } - #endregion - #region Generate SO - generateFoldout = EditorGUILayout.Foldout(generateFoldout, "Generate SO", true, FoldoutStyle); - if (generateFoldout) - { - using (new EditorGUILayout.VerticalScope(SectionBoxStyle)) - { - selectedGenerateType = (ContractType)EditorGUILayout.EnumPopup("Contract Type", selectedGenerateType); - GUILayout.Space(8); - - switch (selectedGenerateType) - { - case ContractType.CurrencyToken: - controller.soContractAddress = EditorGUILayout.TextField("Currency Address", controller.soContractAddress); - controller.soTokenDecimals = EditorGUILayout.IntField("Token Decimals", controller.soTokenDecimals); - GUILayout.Space(8); - - if (GUILayout.Button("Create Currency Token ScriptableObject", ButtonStyle, GUILayout.Height(26))) - { - var asset = CreateInstance(); - asset.contractAddress = controller.soContractAddress; - - string path = EditorUtility.SaveFilePanelInProject("Save ERC20 ScriptableObject", "NewERC20Scriptable", "asset", "Please enter a file name to save the asset to"); - if (!string.IsNullOrEmpty(path)) - { - AssetDatabase.CreateAsset(asset, path); - AssetDatabase.SaveAssets(); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = asset; - } - } - break; - - case ContractType.NFTContract: - controller.soContractAddress = EditorGUILayout.TextField("Contract Address", controller.soContractAddress); - GUILayout.Space(8); - - if (GUILayout.Button("Create NFT Contract ScriptableObject", ButtonStyle, GUILayout.Height(26))) - { - var asset = CreateInstance(); - asset.contractAddress = controller.soContractAddress; - - string path = EditorUtility.SaveFilePanelInProject("Save ERC721 ScriptableObject", "NewERC721Scriptable", "asset", "Please enter a file name to save the asset to"); - if (!string.IsNullOrEmpty(path)) - { - AssetDatabase.CreateAsset(asset, path); - AssetDatabase.SaveAssets(); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = asset; - } - } - - break; - - case ContractType.Web3GameItem: - controller.soContractAddress = EditorGUILayout.TextField("Item Address", controller.soContractAddress); - controller.soSpecifyBurnAddress = EditorGUILayout.Toggle("Specify Burn Address", controller.soSpecifyBurnAddress); - - if (controller.soSpecifyBurnAddress) - { - controller.soContractBurnAddress = EditorGUILayout.TextField("Burn Address", controller.soContractBurnAddress); - - } - GUILayout.Space(8); - - if (GUILayout.Button("Create Web 3 Game Item ScriptableObject", ButtonStyle, GUILayout.Height(26))) - { - var asset = CreateInstance(); - asset.contractAddress = controller.soContractAddress; - asset.specifyBurnAddress = controller.soSpecifyBurnAddress; - - string path = EditorUtility.SaveFilePanelInProject("Save ERC1155 ScriptableObject", "NewERC1155Scriptable", "asset", "Please enter a file name to save the asset to"); - if (!string.IsNullOrEmpty(path)) - { - AssetDatabase.CreateAsset(asset, path); - AssetDatabase.SaveAssets(); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = asset; - } - } - break; - - } - } - } - #endregion - } - - private Texture2D MakeTex(int width, int height, Color col) - { - Color[] pix = new Color[width * height]; - for (int i = 0; i < pix.Length; i++) pix[i] = col; - Texture2D result = new Texture2D(width, height); - result.SetPixels(pix); - result.Apply(); - return result; - } -} - -public enum ContractType -{ - CurrencyToken, - NFTContract, - Web3GameItem, -} - -public enum ContractRole -{ - Minter -} diff --git a/Assets/SidekickEditor/SidekickEditorController.cs b/Assets/SidekickEditor/SidekickEditorController.cs deleted file mode 100644 index db72d80e..00000000 --- a/Assets/SidekickEditor/SidekickEditorController.cs +++ /dev/null @@ -1,572 +0,0 @@ -using UnityEditor; -using UnityEngine; -using System.Text; -using Sequence; -using Sequence.Sidekick; -using Sequence.Provider; -public class SidekickEditorController : MonoBehaviour -{ - - private SequenceSidekickClient sidekick = new SequenceSidekickClient(Chain.TestnetArbitrumSepolia); - - #region Sidekick Wallet - - public void GetWalletAddress() - { - EditorApplication.delayCall += async () => - { - try - { - string result = await sidekick.GetWalletAddress(); - Debug.Log(result); - } - catch (System.Exception ex) - { - Debug.LogError("Failed to recover sidekick wallet address: " + ex.Message); - } - }; - } - - #endregion - - #region Sidekick Contracts - - public void GetContracts() - { - EditorApplication.delayCall += async () => - { - try - { - string result = await sidekick.GetAllContracts(); - Debug.Log(result); - } - catch (System.Exception ex) - { - Debug.LogError("Failed to recover builder contracts: " + ex.Message); - } - }; - } - - #endregion - - #region Deploy - - #region Deploy ERC20 - - public string DeployERC20InitialOwner { get; set; } - public string DeployERC20Name { get; set; } - public string DeployERC20Symbol { get; set; } - - public async void DeployERC20() - { - - var payload = new DeployERC20Payload - { - initialOwner = DeployERC20InitialOwner, - name = DeployERC20Name, - symbol = DeployERC20Symbol - }; - - string jsonString = JsonUtility.ToJson(payload); - - Debug.Log("Deploying ERC20: " + jsonString); - - try - { - string result = await sidekick.DeployERC20(jsonString); - - DeployResult deployResult = JsonUtility.FromJson(result); - - if (!string.IsNullOrEmpty(deployResult.result.txHash)) - { - - var receipt = await new SequenceEthClient(sidekick.Chain).WaitForTransactionReceipt(deployResult.result.txHash); - - if (receipt != null) - { - string deployedAddress = ReceiptExtractor.ExtractFirstContractAddressExceptOwn(receipt, DeployERC20InitialOwner); - if (!string.IsNullOrEmpty(deployedAddress)) - { - Debug.Log($"Deployed contract address: {deployedAddress}"); - } - else - { - Debug.LogWarning("Could not extract deployed contract address from receipt."); - } - } - else - { - Debug.LogError("Failed to get transaction receipt."); - } - } - else - { - Debug.LogError($"Deployment error: {deployResult.result.error}"); - } - } - catch (System.Exception ex) - { - Debug.LogError("Deploy ERC20 failed: " + ex.Message); - } - } - - #endregion - - #region Deploy ERC721 - public string DeployERC721DefaultAdmin { get; set; } - public string DeployERC721Minter { get; set; } - public string DeployERC721Name { get; set; } - public string DeployERC721Symbol { get; set; } - - public async void DeployERC721() - { - var payload = new DeployERC721Payload - { - defaultAdmin = DeployERC721DefaultAdmin, - minter = DeployERC721Minter, - name = DeployERC721Name, - symbol = DeployERC721Symbol - }; - - string jsonString = JsonUtility.ToJson(payload); - - Debug.Log("Deploying ERC721: " + jsonString); - - try - { - string result = await sidekick.DeployERC721(jsonString); - - DeployResult deployResult = JsonUtility.FromJson(result); - - if (!string.IsNullOrEmpty(deployResult.result.txHash)) - { - - var receipt = await new SequenceEthClient(sidekick.Chain).WaitForTransactionReceipt(deployResult.result.txHash); - - if (receipt != null) - { - string deployedAddress = ReceiptExtractor.ExtractFirstContractAddressExceptOwn(receipt, DeployERC721DefaultAdmin); - if (!string.IsNullOrEmpty(deployedAddress)) - { - Debug.Log($"Deployed contract address: {deployedAddress}"); - } - else - { - Debug.LogWarning("Could not extract deployed contract address from receipt."); - } - } - else - { - Debug.LogError("Failed to get transaction receipt."); - } - } - else - { - Debug.LogError($"Deployment error: {deployResult.result.error}"); - } - } - catch (System.Exception ex) - { - Debug.LogError("Deploy ERC721 failed: " + ex.Message); - } - } - - #endregion - - #region Deploy ERC1155 - - public string DeployDefaultAdmin { get; set; } - public string DeployMinter { get; set; } - public string DeployName { get; set; } - - public async void DeployERC1155() - { - var deployPayload = new DeployERC1155Payload - { - defaultAdmin = DeployDefaultAdmin, - minter = DeployMinter, - name = DeployName - }; - - string jsonString = JsonUtility.ToJson(deployPayload); - - Debug.Log("Deploying ERC1155: " + jsonString); - - try - { - string result = await sidekick.DeployERC1155(jsonString); - - DeployResult deployResult = JsonUtility.FromJson(result); - - if (!string.IsNullOrEmpty(deployResult.result.txHash)) - { - var receipt = await new SequenceEthClient(sidekick.Chain).WaitForTransactionReceipt(deployResult.result.txHash); - - if (receipt != null) - { - string deployedAddress = ReceiptExtractor.ExtractFirstContractAddressExceptOwn(receipt, DeployDefaultAdmin); - if (!string.IsNullOrEmpty(deployedAddress)) - { - Debug.Log($"Deployed contract address: {deployedAddress}"); - } - else - { - Debug.LogWarning("Could not extract deployed contract address from receipt."); - } - } - else - { - Debug.LogError("Failed to get transaction receipt."); - } - } - else - { - Debug.LogError($"Deployment error: {deployResult.result.error}"); - } - } - catch (System.Exception ex) - { - Debug.LogError("Deploy ERC1155 failed: " + ex.Message); - } - } - - #endregion - - #endregion - - #region Role - - public ContractRole SelectedContractRole { get; set; } - public string GrantRoleContractAddress { get; set; } - public string GrantRoleRole { get; set; } - public string GrantRoleAccount { get; set; } - - public void GrantERC1155Role() - { - var grantRolePayload = new GrantRolePayload - { - role = GrantRoleRole, - account = GrantRoleAccount - }; - - string jsonString = JsonUtility.ToJson(grantRolePayload); - - Debug.Log("Granting role ERC1155: " + jsonString); - - EditorApplication.delayCall += async () => - { - try - { - string result = await sidekick.GrantRoleERC1155(GrantRoleContractAddress, jsonString); - Debug.Log("Grant role result: " + result); - } - catch (System.Exception ex) - { - Debug.LogError("Grant ERC1155 role failed: " + ex.Message); - } - }; - } - - #endregion - - #region Mint - - #region MintERC20 - - public string MintERC20ContractAddress { get; set; } - public string MintERC20RecipientAddress { get; set; } - public string MintERC20Amount { get; set; } - - public void MintERC20() - { - var mintJson = new MintERC20Payload - { - to = MintERC20RecipientAddress, - amount = MintERC20Amount - }; - string jsonString = JsonUtility.ToJson(mintJson); - - Debug.Log("Minting ERC20: " + jsonString); - - EditorApplication.delayCall += async () => - { - try - { - string result = await sidekick.MintERC20(MintERC20ContractAddress, jsonString); - Debug.Log("Mint result: " + result); - } - catch (System.Exception ex) - { - Debug.LogError("Mint ERC20 failed: " + ex.Message); - } - }; - } - - #endregion - - - #region Mint ERC721 - - public bool IsBatchMintERC721 { get; set; } = false; - public string SafeMintERC721ContractAddress { get; set; } - - public string SafeMintERC721Recipient { get; set; } - public string SafeMintERC721TokenId { get; set; } - - public async void SafeMintERC721() - { - var payload = new SafeMintERC721Payload - { - to = SafeMintERC721Recipient, - tokenId = SafeMintERC721TokenId - }; - string jsonString = JsonUtility.ToJson(payload); - - Debug.Log("Calling safeMint ERC721: " + jsonString); - - try - { - string result = await sidekick.SafeMintERC721(SafeMintERC721ContractAddress, jsonString); - Debug.Log("safeMint result: " + result); - } - catch (System.Exception ex) - { - Debug.LogError("safeMint ERC721 failed: " + ex.Message); - } - } - - public string[] SafeMintERC721BatchRecipients { get; set; } - public string[] SafeMintERC721BatchTokenIds { get; set; } - - public async void SafeMintBatchERC721() - { - var payload = new SafeMintBatchERC721Payload - { - recipients = SafeMintERC721BatchRecipients, - tokenIds = SafeMintERC721BatchTokenIds - }; - string jsonString = JsonUtility.ToJson(payload); - - Debug.Log("Calling safeMintBatch ERC721: " + jsonString); - - try - { - string result = await sidekick.SafeMintBatchERC721(SafeMintERC721ContractAddress, jsonString); - Debug.Log("safeMintBatch result: " + result); - } - catch (System.Exception ex) - { - Debug.LogError("safeMintBatch ERC721 failed: " + ex.Message); - } - } - - #endregion - - #region Mint ERC1155 - - public bool IsBatchMintERC1155 { get; set; } = false; - - public string MintERC1155ContractAddress { get; set; } - - public string MintERC1155RecipientAddress { get; set; } - public string MintERC1155Id { get; set; } - public string MintERC1155Amount { get; set; } - public string MintERC1155Data { get; set; } - public void MintERC1155() - { - var mintJson = new MintERC1155Payload - { - recipient = MintERC1155RecipientAddress, - id = MintERC1155Id, - amount = MintERC1155Amount, - data = ToHexString(MintERC1155Data) - }; - - string jsonString = JsonUtility.ToJson(mintJson); - - Debug.Log("Minting ERC1155: " + jsonString); - - EditorApplication.delayCall += async () => - { - try - { - string result = await sidekick.MintERC1155(MintERC1155ContractAddress, jsonString); - Debug.Log("Mint result: " + result); - } - catch (System.Exception ex) - { - Debug.LogError("Mint ERC1155 failed: " + ex.Message); - } - }; - } - public string[] MintERC1155BatchRecipients { get; set; } = new string[0]; - public string[] MintERC1155BatchIds { get; set; } = new string[0]; - public string[] MintERC1155BatchAmounts { get; set; } = new string[0]; - public string[] MintERC1155BatchDatas { get; set; } = new string[0]; - - public void MintERC1155Batch() - { - string[] hexDatas = new string[MintERC1155BatchDatas.Length]; - - for (int i = 0; i < MintERC1155BatchDatas.Length; i++) - { - hexDatas[i] = ToHexString(MintERC1155BatchDatas[i]); - - } - - var mintJson = new MintERC1155BatchPayload - { - recipients = MintERC1155BatchRecipients, - ids = MintERC1155BatchIds, - amounts = MintERC1155BatchAmounts, - datas = hexDatas - }; - - string jsonString = JsonUtility.ToJson(mintJson); - Debug.Log("Minting ERC1155 Batch: " + jsonString); - - EditorApplication.delayCall += async () => - { - try - { - string result = await sidekick.MintBatchERC1155(MintERC1155ContractAddress, jsonString); - Debug.Log("Mint batch result: " + result); - } - catch (System.Exception ex) - { - Debug.LogError("Mint ERC1155 batch failed: " + ex.Message); - } - }; - } - - #endregion - - - #endregion - - - #region Create SO - - public string soContractAddress { get; set; } - public string soContractBurnAddress { get; set; } - public int soTokenDecimals { get; set; } - public bool soSpecifyBurnAddress { get; set; } - - #endregion - - public string ToHexString(string input) - { - byte[] bytes = Encoding.UTF8.GetBytes(input); - StringBuilder hex = new StringBuilder("0x"); - - foreach (byte b in bytes) - { - hex.Append(b.ToString("x2")); - } - - return hex.ToString(); - } -} - -#region Payloads - -#region Deploy - -[System.Serializable] -public class DeployERC1155Payload -{ - public string defaultAdmin; - public string minter; - public string name; -} - -[System.Serializable] -public class DeployERC20Payload -{ - public string initialOwner; - public string name; - public string symbol; -} - -[System.Serializable] -public class DeployERC721Payload -{ - public string defaultAdmin; - public string minter; - public string name; - public string symbol; -} - -#endregion - -#region Mint - -[System.Serializable] -public class MintERC20Payload -{ - public string to; - public string amount; -} - - -[System.Serializable] -public class SafeMintERC721Payload -{ - public string to; - public string tokenId; -} - -[System.Serializable] -public class SafeMintBatchERC721Payload -{ - public string[] recipients; - public string[] tokenIds; -} -[System.Serializable] -public class MintERC1155Payload -{ - public string recipient; - public string id; - public string amount; - public string data; -} - -[System.Serializable] -public class MintERC1155BatchPayload -{ - public string[] recipients; - public string[] ids; - public string[] amounts; - public string[] datas; -} - - -#endregion - -#region Role - -[System.Serializable] -public class GrantRolePayload -{ - public string role; - public string account; -} - -#endregion - -#endregion - - -[System.Serializable] -public class DeployResult -{ - public ResultData result; - - [System.Serializable] - public class ResultData - { - public string txHash; - public string txUrl; - public string error; - } -} diff --git a/Assets/SidekickEditor.meta b/Packages/Sequence-Unity/Editor/Sidekick.meta similarity index 77% rename from Assets/SidekickEditor.meta rename to Packages/Sequence-Unity/Editor/Sidekick.meta index a1e6ba8c..36e9a334 100644 --- a/Assets/SidekickEditor.meta +++ b/Packages/Sequence-Unity/Editor/Sidekick.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: ca60c91a2b637284081d37835cd4523e +guid: 9470df17bc9a49f429274960a115a103 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/Editor/SidekickDockerUtility.cs b/Packages/Sequence-Unity/Editor/Sidekick/SidekickDockerUtility.cs similarity index 71% rename from Assets/Editor/SidekickDockerUtility.cs rename to Packages/Sequence-Unity/Editor/Sidekick/SidekickDockerUtility.cs index c13e7c7b..287571f0 100644 --- a/Assets/Editor/SidekickDockerUtility.cs +++ b/Packages/Sequence-Unity/Editor/Sidekick/SidekickDockerUtility.cs @@ -3,7 +3,6 @@ using System.Diagnostics; using System.IO; using System.Linq; - public static class SidekickDockerUtility { private static SidekickConfig config; @@ -21,11 +20,29 @@ private static string SidekickPath return string.Empty; } } - return config.path; + return config.sidekickPath; + } + } + + private static string dockerDesktopPath + { + get + { + if (config == null) + { + config = Resources.Load("SidekickConfig"); + if (config == null) + { + UnityEngine.Debug.LogError("Could not load SidekickConfig from Resources."); + return string.Empty; + } + } + return config.dockerDesktopPath; } } - [MenuItem("Sequence Dev/Start Sidekick", false, 0)] + + [MenuItem("Sequence Sidekick/Start", false, 0)] private static void StartSidekick() { if (IsSidekickRunning()) return; @@ -35,10 +52,10 @@ private static void StartSidekick() RunCommand("pnpm docker:restart", SidekickPath); } - [MenuItem("Sequence Dev/Start Sidekick", true)] + [MenuItem("Sequence Sidekick/Start", true)] private static bool ValidateStart() => !IsSidekickRunning(); - [MenuItem("Sequence Dev/Stop Sidekick", false, 1)] + [MenuItem("Sequence Sidekick/Stop", false, 1)] private static void StopSidekick() { if (!IsSidekickRunning()) return; @@ -46,7 +63,7 @@ private static void StopSidekick() RunCommand("pnpm docker:stop", SidekickPath); } - [MenuItem("Sequence Dev/Stop Sidekick", true)] + [MenuItem("Sequence Sidekick/Stop", true)] private static bool ValidateStop() => IsSidekickRunning(); private static void RunCommand(string command, string workingDirectory) @@ -86,40 +103,42 @@ private static void RunCommand(string command, string workingDirectory) process.BeginOutputReadLine(); process.BeginErrorReadLine(); } - private static void EnsureDockerDesktopRunning() { const int maxWaitTimeSeconds = 120; const int pollIntervalMs = 2000; - if (!Process.GetProcessesByName("Docker Desktop").Any()) + System.Threading.Tasks.Task.Run(() => { - string dockerDesktopPath = @"C:\Program Files\Docker\Docker\Docker Desktop.exe"; - if (File.Exists(dockerDesktopPath)) - { - Process.Start(dockerDesktopPath); - } - else + if (!Process.GetProcessesByName("Docker Desktop").Any()) { - UnityEngine.Debug.LogWarning("[Docker] Docker Desktop not found at default path."); - return; + if (File.Exists(config.dockerDesktopPath)) + { + Process.Start(config.dockerDesktopPath); + } + else + { + UnityEngine.Debug.LogWarning("[Docker] Docker Desktop not found at Sidekick Config set path."); + return; + } } - } - var stopwatch = new Stopwatch(); - stopwatch.Start(); + var stopwatch = new Stopwatch(); + stopwatch.Start(); - while (stopwatch.Elapsed.TotalSeconds < maxWaitTimeSeconds) - { - if (IsDockerDaemonReady()) + while (stopwatch.Elapsed.TotalSeconds < maxWaitTimeSeconds) { - return; - } + if (IsDockerDaemonReady()) + { + UnityEngine.Debug.Log("[Docker] Docker is ready."); + return; + } - System.Threading.Thread.Sleep(pollIntervalMs); - } + System.Threading.Thread.Sleep(pollIntervalMs); + } - UnityEngine.Debug.LogError("[Docker] Timed out waiting for Docker to become ready."); + UnityEngine.Debug.LogError("[Docker] Timed out waiting for Docker to become ready."); + }); } private static bool IsDockerDaemonReady() diff --git a/Assets/Editor/SidekickDockerUtility.cs.meta b/Packages/Sequence-Unity/Editor/Sidekick/SidekickDockerUtility.cs.meta similarity index 100% rename from Assets/Editor/SidekickDockerUtility.cs.meta rename to Packages/Sequence-Unity/Editor/Sidekick/SidekickDockerUtility.cs.meta diff --git a/Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.asmdef b/Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.asmdef new file mode 100644 index 00000000..a21413d1 --- /dev/null +++ b/Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.asmdef @@ -0,0 +1,22 @@ +{ + "name": "Sequence.SidekickEditor", + "rootNamespace": "", + "references": [ + "GUID:4e0a798abbda240658187632ae443a67", + "GUID:f7fd4ba36aabd1d499450c174865e70b", + "GUID:b4f9c0f8f363f439b9e337f79050f189", + "GUID:a35e3a53d4439435f8b36ed2c6158cd8", + "GUID:c8f59a655c1ffd54cac5a528235b9f1c" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.asmdef.meta b/Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.asmdef.meta new file mode 100644 index 00000000..ec49d705 --- /dev/null +++ b/Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1115d98b227df534a9e9b3e5092485e9 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.cs b/Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.cs new file mode 100644 index 00000000..3ad6be9c --- /dev/null +++ b/Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.cs @@ -0,0 +1,376 @@ +using UnityEditor; +using UnityEngine; +using System; +using Sequence.Sidekick; + + + + [CustomEditor(typeof(SidekickEditorController))] + public class SidekickEditor : UnityEditor.Editor + { + bool deployFoldout = true; + bool mintFoldout = true; + bool generateFoldout = true; + bool grantRoleFoldout = true; + + ContractType selectedDeployType; + ContractType selectedMintType; + ContractType selectedGenerateType; + + GUIStyle HeaderStyle => new GUIStyle(EditorStyles.label) + { + fontStyle = FontStyle.Bold, + fontSize = 16, + normal = { textColor = new Color(0.9f, 0.9f, 0.9f) } + }; + + GUIStyle FoldoutStyle => new GUIStyle(EditorStyles.foldout) + { + fontStyle = FontStyle.Bold, + fontSize = 14, + normal = { textColor = new Color(0.8f, 0.8f, 0.8f) }, + hover = { textColor = Color.white }, + active = { textColor = Color.white } + }; + + GUIStyle SectionBoxStyle + { + get + { + var style = new GUIStyle(GUI.skin.box); + style.normal.background = MakeTex(2, 2, new Color(0.15f, 0.15f, 0.15f, 0.7f)); + style.margin = new RectOffset(0, 0, 5, 10); + style.padding = new RectOffset(10, 10, 10, 10); + return style; + } + } + GUIStyle ButtonStyle + { + get + { + var style = new GUIStyle(GUI.skin.button) + { + fontStyle = FontStyle.Bold, + fontSize = 13 + }; + + style.normal.textColor = Color.white; + style.hover.textColor = Color.white; + + return style; + } + } + GUIStyle LabelBoldStyle => new GUIStyle(EditorStyles.label) + { + fontStyle = FontStyle.Bold, + fontSize = 12, + normal = { textColor = Color.white } + }; + + public override void OnInspectorGUI() + { + var controller = (SidekickEditorController)target; + + EditorGUILayout.Space(8); + EditorGUILayout.LabelField("Sidekick Wallet", HeaderStyle); + + GUILayout.Space(6); + if (GUILayout.Button("Get Wallet Address", ButtonStyle, GUILayout.Height(28))) + controller.GetWalletAddress(); + + //GUILayout.Space(6); + //if (GUILayout.Button("Get Contracts", ButtonStyle, GUILayout.Height(28))) + // controller.GetContracts(); + + EditorGUILayout.Space(14); + + #region Deploy + deployFoldout = EditorGUILayout.Foldout(deployFoldout, "Deploy", true, FoldoutStyle); + if (deployFoldout) + { + using (new EditorGUILayout.VerticalScope(SectionBoxStyle)) + { + selectedDeployType = (ContractType)EditorGUILayout.EnumPopup("Contract Type", selectedDeployType); + + EditorGUILayout.Space(); + + switch (selectedDeployType) + { + case ContractType.CurrencyToken: + controller.DeployERC20InitialOwner = EditorGUILayout.TextField("Initial Owner", controller.DeployERC20InitialOwner); + controller.DeployERC20Name = EditorGUILayout.TextField("Name", controller.DeployERC20Name); + controller.DeployERC20Symbol = EditorGUILayout.TextField("Symbol", controller.DeployERC20Symbol); + GUILayout.Space(8); + if (GUILayout.Button("Deploy Currency Token", ButtonStyle, GUILayout.Height(26))) + controller.DeployERC20(); + break; + + case ContractType.NFTContract: + controller.DeployERC721DefaultAdmin = EditorGUILayout.TextField("Default Admin", controller.DeployERC721DefaultAdmin); + controller.DeployERC721Minter = EditorGUILayout.TextField("Minter", controller.DeployERC721Minter); + controller.DeployERC721Name = EditorGUILayout.TextField("Name", controller.DeployERC721Name); + controller.DeployERC721Symbol = EditorGUILayout.TextField("Symbol", controller.DeployERC721Symbol); + GUILayout.Space(8); + if (GUILayout.Button("Deploy NFT Contract", ButtonStyle, GUILayout.Height(26))) + controller.DeployERC721(); + break; + + case ContractType.Web3GameItem: + controller.DeployDefaultAdmin = EditorGUILayout.TextField("Default Admin", controller.DeployDefaultAdmin); + controller.DeployMinter = EditorGUILayout.TextField("Minter", controller.DeployMinter); + controller.DeployName = EditorGUILayout.TextField("Name", controller.DeployName); + GUILayout.Space(8); + if (GUILayout.Button("Deploy Web 3 Game Item", ButtonStyle, GUILayout.Height(26))) + controller.DeployERC1155(); + break; + } + } + } + #endregion + + #region Grant Role + grantRoleFoldout = EditorGUILayout.Foldout(grantRoleFoldout, "Grant Role", true, FoldoutStyle); + if (grantRoleFoldout) + { + using (new EditorGUILayout.VerticalScope(SectionBoxStyle)) + { + controller.SelectedContractRole = (ContractRole)EditorGUILayout.EnumPopup("Role", controller.SelectedContractRole); + + switch (controller.SelectedContractRole) + { + case ContractRole.Minter: + controller.GrantRoleRole = "0xdfd8f10cabf255ee49ecf3db8b4502eea7eac26c270f6e5f0f28506f6f3fbb55"; + break; + default: + throw new ArgumentOutOfRangeException(nameof(controller.SelectedContractRole), "Unsupported role"); + } + + controller.GrantRoleContractAddress = EditorGUILayout.TextField("Contract Address", controller.GrantRoleContractAddress); + controller.GrantRoleAccount = EditorGUILayout.TextField("Account Address", controller.GrantRoleAccount); + + GUILayout.Space(8); + + if (GUILayout.Button("Grant Role", ButtonStyle, GUILayout.Height(26))) + controller.GrantERC1155Role(); + } + } + #endregion + + #region Mint + mintFoldout = EditorGUILayout.Foldout(mintFoldout, "Mint", true, FoldoutStyle); + if (mintFoldout) + { + using (new EditorGUILayout.VerticalScope(SectionBoxStyle)) + { + selectedMintType = (ContractType)EditorGUILayout.EnumPopup("Item Type", selectedMintType); + GUILayout.Space(6); + + switch (selectedMintType) + { + case ContractType.CurrencyToken: + controller.MintERC20ContractAddress = EditorGUILayout.TextField("Currency Address", controller.MintERC20ContractAddress); + controller.MintERC20RecipientAddress = EditorGUILayout.TextField("Recipient Address", controller.MintERC20RecipientAddress); + controller.MintERC20Amount = EditorGUILayout.TextField("Amount", controller.MintERC20Amount); + GUILayout.Space(8); + if (GUILayout.Button("Mint CurrencyToken", ButtonStyle, GUILayout.Height(26))) + controller.MintERC20(); + break; + + case ContractType.NFTContract: + controller.SafeMintERC721ContractAddress = EditorGUILayout.TextField("NFT Contract Address", controller.SafeMintERC721ContractAddress); + controller.IsBatchMintERC721 = EditorGUILayout.Toggle("Batch Mint", controller.IsBatchMintERC721); + + GUILayout.Space(8); + + if (controller.IsBatchMintERC721) + { + int batchSize = controller.SafeMintERC721BatchRecipients?.Length ?? 0; + batchSize = EditorGUILayout.IntField("Batch Size", batchSize); + batchSize = Mathf.Max(batchSize, 0); + GUILayout.Space(6); + + var recipients = controller.SafeMintERC721BatchRecipients ?? new string[0]; + var tokenIds = controller.SafeMintERC721BatchTokenIds ?? new string[0]; + + if (recipients.Length != batchSize) + Array.Resize(ref recipients, batchSize); + if (tokenIds.Length != batchSize) + Array.Resize(ref tokenIds, batchSize); + + for (int i = 0; i < batchSize; i++) + { + EditorGUILayout.LabelField($"Mint {i + 1}", LabelBoldStyle); + recipients[i] = EditorGUILayout.TextField("Recipient", recipients[i]); + tokenIds[i] = EditorGUILayout.TextField("Token ID", tokenIds[i]); + GUILayout.Space(6); + } + + controller.SafeMintERC721BatchRecipients = recipients; + controller.SafeMintERC721BatchTokenIds = tokenIds; + + if (GUILayout.Button("Mint NFT Contract Batch", ButtonStyle, GUILayout.Height(26))) + controller.SafeMintBatchERC721(); + } + else + { + controller.SafeMintERC721Recipient = EditorGUILayout.TextField("Recipient Address", controller.SafeMintERC721Recipient); + controller.SafeMintERC721TokenId = EditorGUILayout.TextField("Token ID", controller.SafeMintERC721TokenId); + GUILayout.Space(8); + if (GUILayout.Button("Mint NFT Contract", ButtonStyle, GUILayout.Height(26))) + controller.SafeMintERC721(); + } + break; + + case ContractType.Web3GameItem: + controller.MintERC1155ContractAddress = EditorGUILayout.TextField("Item Address", controller.MintERC1155ContractAddress); + controller.IsBatchMintERC1155 = EditorGUILayout.Toggle("Batch Mint", controller.IsBatchMintERC1155); + GUILayout.Space(8); + + if (controller.IsBatchMintERC1155) + { + int batchSize = controller.MintERC1155BatchRecipients?.Length ?? 0; + batchSize = EditorGUILayout.IntField("Batch Size", batchSize); + batchSize = Mathf.Max(batchSize, 0); + GUILayout.Space(6); + + var recipients = controller.MintERC1155BatchRecipients ?? new string[0]; + var ids = controller.MintERC1155BatchIds ?? new string[0]; + var amounts = controller.MintERC1155BatchAmounts ?? new string[0]; + var datas = controller.MintERC1155BatchDatas ?? new string[0]; + + if (recipients.Length != batchSize) Array.Resize(ref recipients, batchSize); + if (ids.Length != batchSize) Array.Resize(ref ids, batchSize); + if (amounts.Length != batchSize) Array.Resize(ref amounts, batchSize); + if (datas.Length != batchSize) Array.Resize(ref datas, batchSize); + + for (int i = 0; i < batchSize; i++) + { + EditorGUILayout.LabelField($"Mint {i + 1}", LabelBoldStyle); + recipients[i] = EditorGUILayout.TextField("Recipient", recipients[i]); + ids[i] = EditorGUILayout.TextField("ID", ids[i]); + amounts[i] = EditorGUILayout.TextField("Amount", amounts[i]); + datas[i] = EditorGUILayout.TextField("Data", datas[i]); + GUILayout.Space(6); + } + + controller.MintERC1155BatchRecipients = recipients; + controller.MintERC1155BatchIds = ids; + controller.MintERC1155BatchAmounts = amounts; + controller.MintERC1155BatchDatas = datas; + + if (GUILayout.Button("Mint Web 3 Game Item Batch", ButtonStyle, GUILayout.Height(26))) + controller.MintERC1155Batch(); + } + else + { + controller.MintERC1155RecipientAddress = EditorGUILayout.TextField("Recipient Address", controller.MintERC1155RecipientAddress); + controller.MintERC1155Id = EditorGUILayout.TextField("ID", controller.MintERC1155Id); + controller.MintERC1155Amount = EditorGUILayout.TextField("Amount", controller.MintERC1155Amount); + controller.MintERC1155Data = EditorGUILayout.TextField("Data", controller.MintERC1155Data); + GUILayout.Space(8); + if (GUILayout.Button("Mint Web 3 Game Item", ButtonStyle, GUILayout.Height(26))) + controller.MintERC1155(); + } + break; + } + } + } + #endregion + #region Generate SO + generateFoldout = EditorGUILayout.Foldout(generateFoldout, "Generate SO", true, FoldoutStyle); + if (generateFoldout) + { + using (new EditorGUILayout.VerticalScope(SectionBoxStyle)) + { + selectedGenerateType = (ContractType)EditorGUILayout.EnumPopup("Contract Type", selectedGenerateType); + GUILayout.Space(8); + + switch (selectedGenerateType) + { + case ContractType.CurrencyToken: + controller.soContractAddress = EditorGUILayout.TextField("Currency Address", controller.soContractAddress); + controller.soTokenDecimals = EditorGUILayout.IntField("Token Decimals", controller.soTokenDecimals); + GUILayout.Space(8); + + if (GUILayout.Button("Create Currency Token ScriptableObject", ButtonStyle, GUILayout.Height(26))) + { + var asset = CreateInstance(); + asset.contractAddress = controller.soContractAddress; + + string path = EditorUtility.SaveFilePanelInProject("Save ERC20 ScriptableObject", "NewERC20Scriptable", "asset", "Please enter a file name to save the asset to"); + if (!string.IsNullOrEmpty(path)) + { + AssetDatabase.CreateAsset(asset, path); + AssetDatabase.SaveAssets(); + EditorUtility.FocusProjectWindow(); + Selection.activeObject = asset; + } + } + break; + + case ContractType.NFTContract: + controller.soContractAddress = EditorGUILayout.TextField("Contract Address", controller.soContractAddress); + GUILayout.Space(8); + + if (GUILayout.Button("Create NFT Contract ScriptableObject", ButtonStyle, GUILayout.Height(26))) + { + var asset = CreateInstance(); + asset.contractAddress = controller.soContractAddress; + + string path = EditorUtility.SaveFilePanelInProject("Save ERC721 ScriptableObject", "NewERC721Scriptable", "asset", "Please enter a file name to save the asset to"); + if (!string.IsNullOrEmpty(path)) + { + AssetDatabase.CreateAsset(asset, path); + AssetDatabase.SaveAssets(); + EditorUtility.FocusProjectWindow(); + Selection.activeObject = asset; + } + } + + break; + + case ContractType.Web3GameItem: + controller.soContractAddress = EditorGUILayout.TextField("Item Address", controller.soContractAddress); + controller.soSpecifyBurnAddress = EditorGUILayout.Toggle("Specify Burn Address", controller.soSpecifyBurnAddress); + + if (controller.soSpecifyBurnAddress) + { + controller.soContractBurnAddress = EditorGUILayout.TextField("Burn Address", controller.soContractBurnAddress); + + } + GUILayout.Space(8); + + if (GUILayout.Button("Create Web 3 Game Item ScriptableObject", ButtonStyle, GUILayout.Height(26))) + { + var asset = CreateInstance(); + asset.contractAddress = controller.soContractAddress; + asset.specifyBurnAddress = controller.soSpecifyBurnAddress; + + string path = EditorUtility.SaveFilePanelInProject("Save ERC1155 ScriptableObject", "NewERC1155Scriptable", "asset", "Please enter a file name to save the asset to"); + if (!string.IsNullOrEmpty(path)) + { + AssetDatabase.CreateAsset(asset, path); + AssetDatabase.SaveAssets(); + EditorUtility.FocusProjectWindow(); + Selection.activeObject = asset; + } + } + break; + + } + } + } + #endregion + } + + private Texture2D MakeTex(int width, int height, Color col) + { + Color[] pix = new Color[width * height]; + for (int i = 0; i < pix.Length; i++) pix[i] = col; + Texture2D result = new Texture2D(width, height); + result.SetPixels(pix); + result.Apply(); + return result; + } + } + diff --git a/Assets/SidekickEditor/SidekickEditor.cs.meta b/Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.cs.meta similarity index 100% rename from Assets/SidekickEditor/SidekickEditor.cs.meta rename to Packages/Sequence-Unity/Editor/Sidekick/SidekickEditor.cs.meta diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Config/SidekickConfig.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/Config/SidekickConfig.cs index 39553e65..9bcbfd0e 100644 --- a/Packages/Sequence-Unity/Sequence/SequenceSDK/Config/SidekickConfig.cs +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Config/SidekickConfig.cs @@ -1,7 +1,9 @@ using UnityEngine; -[CreateAssetMenu(fileName = "SidekickConfig", menuName = "ScriptableObjects/SidekickConfig")] +[CreateAssetMenu(fileName = "SidekickConfig", menuName = "Sequence/SidekickConfig")] public class SidekickConfig : ScriptableObject { - public string path; + public string secretKey; + public string sidekickPath; + public string dockerDesktopPath; } \ No newline at end of file diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs index 23c7de47..8811fb11 100644 --- a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs @@ -4,13 +4,12 @@ using System.Threading.Tasks; using UnityEngine; -namespace Sequence.Sidekick +namespace Sequence.EmbeddedWallet { public class SequenceSidekickClient { - private static readonly HttpClient client = new(); + private static readonly System.Net.Http.HttpClient client = new(); private string baseUrl = "http://localhost:3000"; - private string secretKey = "ultrasecretkey"; public Chain Chain; @@ -48,7 +47,7 @@ private async Task PostAsync(string endpoint, string json) using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url)) { - request.Headers.Add("x-secret-key", secretKey); + request.Headers.Add("x-secret-key", Resources.Load("SidekickConfig").secretKey); var content = new StringContent(json, Encoding.UTF8, "application/json"); request.Content = content; @@ -62,7 +61,7 @@ private async Task PostAsync(string endpoint, string json) } catch (HttpRequestException e) { - throw; + throw new System.Exception(e.Message); } } } diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs.meta b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs.meta index 3f91bcd2..d004ce6f 100644 --- a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs.meta +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/SequenceSidekickClient.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 3c6ce8681ba99e3429b20ec48ba54335 +guid: f4a9e5d7422bad042bf9aac61897a164 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/DeployedContractAddressExtractor.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/DeployedContractAddressExtractor.cs similarity index 91% rename from Assets/DeployedContractAddressExtractor.cs rename to Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/DeployedContractAddressExtractor.cs index 41f9aab7..20da2c5f 100644 --- a/Assets/DeployedContractAddressExtractor.cs +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/DeployedContractAddressExtractor.cs @@ -1,6 +1,6 @@ -namespace Sequence +namespace Sequence.EmbeddedWallet { - public static class ReceiptExtractor + public static class DeployedeContractAddressExtractor { public static string ExtractFirstContractAddressExceptOwn(TransactionReceipt receipt, string ownContractAddress) { diff --git a/Assets/DeployedContractAddressExtractor.cs.meta b/Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/DeployedContractAddressExtractor.cs.meta similarity index 100% rename from Assets/DeployedContractAddressExtractor.cs.meta rename to Packages/Sequence-Unity/Sequence/SequenceSDK/Ethereum/Contract/DeployedContractAddressExtractor.cs.meta diff --git a/Assets/SequenceSDK/Marketplace/SideKick.meta b/Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick.meta similarity index 77% rename from Assets/SequenceSDK/Marketplace/SideKick.meta rename to Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick.meta index 8916b6b2..efc08b16 100644 --- a/Assets/SequenceSDK/Marketplace/SideKick.meta +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: d3f2ac871ca482d49be6994b4018becb +guid: e8ac46c277919214fa23a6ae009fcfa0 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SequenceSidekick.asmdef b/Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SequenceSidekick.asmdef new file mode 100644 index 00000000..eaa651f3 --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SequenceSidekick.asmdef @@ -0,0 +1,17 @@ +{ + "name": "SequenceSidekick", + "rootNamespace": "", + "references": [ + "GUID:4e0a798abbda240658187632ae443a67", + "GUID:f7fd4ba36aabd1d499450c174865e70b" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SequenceSidekick.asmdef.meta b/Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SequenceSidekick.asmdef.meta new file mode 100644 index 00000000..671ff3d7 --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SequenceSidekick.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c8f59a655c1ffd54cac5a528235b9f1c +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SidekickEditorController.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SidekickEditorController.cs new file mode 100644 index 00000000..eb97cb3e --- /dev/null +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SidekickEditorController.cs @@ -0,0 +1,588 @@ +using UnityEditor; +using UnityEngine; +using System.Text; +using Sequence.EmbeddedWallet; +using Sequence.Provider; + +namespace Sequence.Sidekick +{ + public class SidekickEditorController : MonoBehaviour + { + private SequenceSidekickClient sidekick = new SequenceSidekickClient(Chain.TestnetArbitrumSepolia); + + #region Sidekick Wallet + + public void GetWalletAddress() + { + EditorApplication.delayCall += async () => + { + try + { + string result = await sidekick.GetWalletAddress(); + Debug.Log(result); + } + catch (System.Exception ex) + { + Debug.LogError("Failed to recover sidekick wallet address: " + ex.Message); + } + }; + } + + #endregion + + #region Sidekick Contracts + + public void GetContracts() + { + EditorApplication.delayCall += async () => + { + try + { + string result = await sidekick.GetAllContracts(); + Debug.Log(result); + } + catch (System.Exception ex) + { + Debug.LogError("Failed to recover builder contracts: " + ex.Message); + } + }; + } + + #endregion + + #region Deploy + + #region Deploy ERC20 + + public string DeployERC20InitialOwner { get; set; } + public string DeployERC20Name { get; set; } + public string DeployERC20Symbol { get; set; } + + public async void DeployERC20() + { + + var payload = new DeployERC20Payload + { + initialOwner = DeployERC20InitialOwner, + name = DeployERC20Name, + symbol = DeployERC20Symbol + }; + + string jsonString = JsonUtility.ToJson(payload); + + Debug.Log("Deploying ERC20: " + jsonString); + + try + { + string result = await sidekick.DeployERC20(jsonString); + + DeployResult deployResult = JsonUtility.FromJson(result); + + if (!string.IsNullOrEmpty(deployResult.result.txHash)) + { + + var receipt = await new SequenceEthClient(sidekick.Chain).WaitForTransactionReceipt(deployResult.result.txHash); + + if (receipt != null) + { + string deployedAddress = DeployedeContractAddressExtractor.ExtractFirstContractAddressExceptOwn(receipt, DeployERC20InitialOwner); + if (!string.IsNullOrEmpty(deployedAddress)) + { + Debug.Log($"Deployed contract address: {deployedAddress}"); + } + else + { + Debug.LogWarning("Could not extract deployed contract address from receipt."); + } + } + else + { + Debug.LogError("Failed to get transaction receipt."); + } + } + else + { + Debug.LogError($"Deployment error: {deployResult.result.error}"); + } + } + catch (System.Exception ex) + { + Debug.LogError("Deploy ERC20 failed: " + ex.Message); + } + } + + #endregion + + #region Deploy ERC721 + public string DeployERC721DefaultAdmin { get; set; } + public string DeployERC721Minter { get; set; } + public string DeployERC721Name { get; set; } + public string DeployERC721Symbol { get; set; } + + public async void DeployERC721() + { + var payload = new DeployERC721Payload + { + defaultAdmin = DeployERC721DefaultAdmin, + minter = DeployERC721Minter, + name = DeployERC721Name, + symbol = DeployERC721Symbol + }; + + string jsonString = JsonUtility.ToJson(payload); + + Debug.Log("Deploying ERC721: " + jsonString); + + try + { + string result = await sidekick.DeployERC721(jsonString); + + DeployResult deployResult = JsonUtility.FromJson(result); + + if (!string.IsNullOrEmpty(deployResult.result.txHash)) + { + + var receipt = await new SequenceEthClient(sidekick.Chain).WaitForTransactionReceipt(deployResult.result.txHash); + + if (receipt != null) + { + string deployedAddress = DeployedeContractAddressExtractor.ExtractFirstContractAddressExceptOwn(receipt, DeployERC721DefaultAdmin); + if (!string.IsNullOrEmpty(deployedAddress)) + { + Debug.Log($"Deployed contract address: {deployedAddress}"); + } + else + { + Debug.LogWarning("Could not extract deployed contract address from receipt."); + } + } + else + { + Debug.LogError("Failed to get transaction receipt."); + } + } + else + { + Debug.LogError($"Deployment error: {deployResult.result.error}"); + } + } + catch (System.Exception ex) + { + Debug.LogError("Deploy ERC721 failed: " + ex.Message); + } + } + + #endregion + + #region Deploy ERC1155 + + public string DeployDefaultAdmin { get; set; } + public string DeployMinter { get; set; } + public string DeployName { get; set; } + + public async void DeployERC1155() + { + var deployPayload = new DeployERC1155Payload + { + defaultAdmin = DeployDefaultAdmin, + minter = DeployMinter, + name = DeployName + }; + + string jsonString = JsonUtility.ToJson(deployPayload); + + Debug.Log("Deploying ERC1155: " + jsonString); + + try + { + string result = await sidekick.DeployERC1155(jsonString); + + DeployResult deployResult = JsonUtility.FromJson(result); + + if (!string.IsNullOrEmpty(deployResult.result.txHash)) + { + var receipt = await new SequenceEthClient(sidekick.Chain).WaitForTransactionReceipt(deployResult.result.txHash); + + if (receipt != null) + { + string deployedAddress = DeployedeContractAddressExtractor.ExtractFirstContractAddressExceptOwn(receipt, DeployDefaultAdmin); + if (!string.IsNullOrEmpty(deployedAddress)) + { + Debug.Log($"Deployed contract address: {deployedAddress}"); + } + else + { + Debug.LogWarning("Could not extract deployed contract address from receipt."); + } + } + else + { + Debug.LogError("Failed to get transaction receipt."); + } + } + else + { + Debug.LogError($"Deployment error: {deployResult.result.error}"); + } + } + catch (System.Exception ex) + { + Debug.LogError("Deploy ERC1155 failed: " + ex.Message); + } + } + + #endregion + + #endregion + + #region Role + + public ContractRole SelectedContractRole { get; set; } + public string GrantRoleContractAddress { get; set; } + public string GrantRoleRole { get; set; } + public string GrantRoleAccount { get; set; } + + public void GrantERC1155Role() + { + var grantRolePayload = new GrantRolePayload + { + role = GrantRoleRole, + account = GrantRoleAccount + }; + + string jsonString = JsonUtility.ToJson(grantRolePayload); + + Debug.Log("Granting role ERC1155: " + jsonString); + + EditorApplication.delayCall += async () => + { + try + { + string result = await sidekick.GrantRoleERC1155(GrantRoleContractAddress, jsonString); + Debug.Log("Grant role result: " + result); + } + catch (System.Exception ex) + { + Debug.LogError("Grant ERC1155 role failed: " + ex.Message); + } + }; + } + + #endregion + + #region Mint + + #region MintERC20 + + public string MintERC20ContractAddress { get; set; } + public string MintERC20RecipientAddress { get; set; } + public string MintERC20Amount { get; set; } + + public void MintERC20() + { + var mintJson = new MintERC20Payload + { + to = MintERC20RecipientAddress, + amount = MintERC20Amount + }; + string jsonString = JsonUtility.ToJson(mintJson); + + Debug.Log("Minting ERC20: " + jsonString); + + EditorApplication.delayCall += async () => + { + try + { + string result = await sidekick.MintERC20(MintERC20ContractAddress, jsonString); + Debug.Log("Mint result: " + result); + } + catch (System.Exception ex) + { + Debug.LogError("Mint ERC20 failed: " + ex.Message); + } + }; + } + + #endregion + + + #region Mint ERC721 + + public bool IsBatchMintERC721 { get; set; } = false; + public string SafeMintERC721ContractAddress { get; set; } + + public string SafeMintERC721Recipient { get; set; } + public string SafeMintERC721TokenId { get; set; } + + public async void SafeMintERC721() + { + var payload = new SafeMintERC721Payload + { + to = SafeMintERC721Recipient, + tokenId = SafeMintERC721TokenId + }; + string jsonString = JsonUtility.ToJson(payload); + + Debug.Log("Calling safeMint ERC721: " + jsonString); + + try + { + string result = await sidekick.SafeMintERC721(SafeMintERC721ContractAddress, jsonString); + Debug.Log("safeMint result: " + result); + } + catch (System.Exception ex) + { + Debug.LogError("safeMint ERC721 failed: " + ex.Message); + } + } + + public string[] SafeMintERC721BatchRecipients { get; set; } + public string[] SafeMintERC721BatchTokenIds { get; set; } + + public async void SafeMintBatchERC721() + { + var payload = new SafeMintBatchERC721Payload + { + recipients = SafeMintERC721BatchRecipients, + tokenIds = SafeMintERC721BatchTokenIds + }; + string jsonString = JsonUtility.ToJson(payload); + + Debug.Log("Calling safeMintBatch ERC721: " + jsonString); + + try + { + string result = await sidekick.SafeMintBatchERC721(SafeMintERC721ContractAddress, jsonString); + Debug.Log("safeMintBatch result: " + result); + } + catch (System.Exception ex) + { + Debug.LogError("safeMintBatch ERC721 failed: " + ex.Message); + } + } + + #endregion + + #region Mint ERC1155 + + public bool IsBatchMintERC1155 { get; set; } = false; + + public string MintERC1155ContractAddress { get; set; } + + public string MintERC1155RecipientAddress { get; set; } + public string MintERC1155Id { get; set; } + public string MintERC1155Amount { get; set; } + public string MintERC1155Data { get; set; } + public void MintERC1155() + { + var mintJson = new MintERC1155Payload + { + recipient = MintERC1155RecipientAddress, + id = MintERC1155Id, + amount = MintERC1155Amount, + data = ToHexString(MintERC1155Data) + }; + + string jsonString = JsonUtility.ToJson(mintJson); + + Debug.Log("Minting ERC1155: " + jsonString); + + EditorApplication.delayCall += async () => + { + try + { + string result = await sidekick.MintERC1155(MintERC1155ContractAddress, jsonString); + Debug.Log("Mint result: " + result); + } + catch (System.Exception ex) + { + Debug.LogError("Mint ERC1155 failed: " + ex.Message); + } + }; + } + public string[] MintERC1155BatchRecipients { get; set; } = new string[0]; + public string[] MintERC1155BatchIds { get; set; } = new string[0]; + public string[] MintERC1155BatchAmounts { get; set; } = new string[0]; + public string[] MintERC1155BatchDatas { get; set; } = new string[0]; + + public void MintERC1155Batch() + { + string[] hexDatas = new string[MintERC1155BatchDatas.Length]; + + for (int i = 0; i < MintERC1155BatchDatas.Length; i++) + { + hexDatas[i] = ToHexString(MintERC1155BatchDatas[i]); + + } + + var mintJson = new MintERC1155BatchPayload + { + recipients = MintERC1155BatchRecipients, + ids = MintERC1155BatchIds, + amounts = MintERC1155BatchAmounts, + datas = hexDatas + }; + + string jsonString = JsonUtility.ToJson(mintJson); + Debug.Log("Minting ERC1155 Batch: " + jsonString); + + EditorApplication.delayCall += async () => + { + try + { + string result = await sidekick.MintBatchERC1155(MintERC1155ContractAddress, jsonString); + Debug.Log("Mint batch result: " + result); + } + catch (System.Exception ex) + { + Debug.LogError("Mint ERC1155 batch failed: " + ex.Message); + } + }; + } + + #endregion + + + #endregion + + + #region Create SO + + public string soContractAddress { get; set; } + public string soContractBurnAddress { get; set; } + public int soTokenDecimals { get; set; } + public bool soSpecifyBurnAddress { get; set; } + + #endregion + + public string ToHexString(string input) + { + byte[] bytes = Encoding.UTF8.GetBytes(input); + StringBuilder hex = new StringBuilder("0x"); + + foreach (byte b in bytes) + { + hex.Append(b.ToString("x2")); + } + + return hex.ToString(); + } + } + +} + +#region Payloads + +#region Deploy + +[System.Serializable] +public class DeployERC1155Payload +{ + public string defaultAdmin; + public string minter; + public string name; +} + +[System.Serializable] +public class DeployERC20Payload +{ + public string initialOwner; + public string name; + public string symbol; +} + +[System.Serializable] +public class DeployERC721Payload +{ + public string defaultAdmin; + public string minter; + public string name; + public string symbol; +} + +#endregion + +#region Mint + +[System.Serializable] +public class MintERC20Payload +{ + public string to; + public string amount; +} + + +[System.Serializable] +public class SafeMintERC721Payload +{ + public string to; + public string tokenId; +} + +[System.Serializable] +public class SafeMintBatchERC721Payload +{ + public string[] recipients; + public string[] tokenIds; +} +[System.Serializable] +public class MintERC1155Payload +{ + public string recipient; + public string id; + public string amount; + public string data; +} + +[System.Serializable] +public class MintERC1155BatchPayload +{ + public string[] recipients; + public string[] ids; + public string[] amounts; + public string[] datas; +} + + +#endregion + +#region Role + +[System.Serializable] +public class GrantRolePayload +{ + public string role; + public string account; +} + +#endregion + +#endregion + + +[System.Serializable] +public class DeployResult +{ + public ResultData result; + + [System.Serializable] + public class ResultData + { + public string txHash; + public string txUrl; + public string error; + } +} + +public enum ContractType +{ + CurrencyToken, + NFTContract, + Web3GameItem, +} + +public enum ContractRole +{ + Minter +} + diff --git a/Assets/SidekickEditor/SidekickEditorController.cs.meta b/Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SidekickEditorController.cs.meta similarity index 100% rename from Assets/SidekickEditor/SidekickEditorController.cs.meta rename to Packages/Sequence-Unity/Sequence/SequenceSDK/Sidekick/SidekickEditorController.cs.meta