Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feat/fa2' into fix/fa2-main-conflicts
Browse files Browse the repository at this point in the history
k-karuna authored Jul 11, 2023

Verified

This commit was signed with the committer’s verified signature.
fiji-flo Florian Dieminger
2 parents e476852 + 64cfaa1 commit 104de63
Showing 42 changed files with 503 additions and 233 deletions.
File renamed without changes.
35 changes: 35 additions & 0 deletions Runtime/Scripts/FileUploaders/BaseUploader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Collections;
using TezosSDK.Scripts.FileUploaders.IPFS;
using UnityEngine;

namespace TezosSDK.Scripts.FileUploaders
{
public abstract class BaseUploader : MonoBehaviour
{
public string SupportedFileExtensions { get; } = ".jpg, .jpeg, .png";

private void Start()
{
DontDestroyOnLoad(gameObject);
}
}

public interface IPinataUploader : IBaseUploader
{
PinataCredentials PinataCredentials { get; set; }
}

public interface IBaseUploader
{
string SupportedFileExtensions { get; }

/// <summary>
/// Upload file that user will select through native menu file picker.
/// </summary>
/// <param name="callback">
/// Executes after asset uploaded with data address.
/// </param>
IEnumerator UploadFile(Action<string> callback);
}
}
3 changes: 3 additions & 0 deletions Runtime/Scripts/FileUploaders/IPFS.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -3,15 +3,18 @@
using System.Collections;
using System.IO;
using System.Text.Json;
using TezosSDK.Scripts.IpfsUploader;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;
using Logger = TezosSDK.Helpers.Logger;

namespace TezosSDK.Scripts.IpfsUploader
namespace TezosSDK.Scripts.FileUploaders.IPFS
{
public class EditorUploader : BaseUploader, IFileUploader
public class EditorPinataUploader : BaseUploader, IPinataUploader
{
public PinataCredentials PinataCredentials { get; set; }

public IEnumerator UploadFile(Action<string> callback)
{
yield return null;
@@ -28,8 +31,8 @@ public IEnumerator UploadFile(Action<string> callback)
var form = new WWWForm();
form.AddBinaryData("file", File.ReadAllBytes(path), filename);

var request = UnityWebRequest.Post(ApiUrl, form);
request.SetRequestHeader("Authorization", $"Bearer {ApiKey}");
var request = UnityWebRequest.Post(PinataCredentials.ApiUrl, form);
request.SetRequestHeader("Authorization", $"Bearer {PinataCredentials.ApiKey}");
yield return request.SendWebRequest();

if (request.result == UnityWebRequest.Result.Success)
@@ -44,4 +47,4 @@ public IEnumerator UploadFile(Action<string> callback)
}
}
}
#endif
#endif
14 changes: 14 additions & 0 deletions Runtime/Scripts/FileUploaders/IPFS/PinataCredentials.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace TezosSDK.Scripts.FileUploaders.IPFS
{
public class PinataCredentials
{
public string ApiUrl { get; }
public string ApiKey { get; }

public PinataCredentials(string apiKey)
{
ApiUrl = "https://api.pinata.cloud/pinning/pinFileToIPFS";
ApiKey = apiKey;
}
}
}
3 changes: 3 additions & 0 deletions Runtime/Scripts/FileUploaders/IPFS/PinataCredentials.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -2,44 +2,49 @@
using System.Collections;
using System.Runtime.InteropServices;
using System.Text.Json;
using TezosSDK.Scripts.IpfsUploader;
using UnityEngine;

namespace TezosSDK.Scripts.IpfsUploader
namespace TezosSDK.Scripts.FileUploaders.IPFS
{
public class WebUploader : BaseUploader, IFileUploader
public class WebPinataUploader : BaseUploader, IPinataUploader
{
public PinataCredentials PinataCredentials { get; set; }

public void FileRequestCallback(string path)
{
WebUploaderHelper.SetResult(path);
WebPinataUploaderHelper.SetResult(path);
}

public IEnumerator UploadFile(Action<string> callback)
{
yield return null;
WebUploaderHelper.RequestFile(callback, SupportedFileExtensions);
WebPinataUploaderHelper.RequestFile(callback, SupportedFileExtensions);
}
}
public static class WebUploaderHelper

public static class WebPinataUploaderHelper
{
private static Action<string> _responseCallback;

public static WebUploader InitWebFileLoader()
public static IPinataUploader GetUploader(string apiKey)
{
const string callbackObjectName = nameof(WebUploader);
const string callbackMethodName = nameof(WebUploader.FileRequestCallback);
const string callbackObjectName = nameof(WebPinataUploader);
const string callbackMethodName = nameof(WebPinataUploader.FileRequestCallback);

var webUploaderGameObject = GameObject.Find(nameof(WebUploader));
var webUploaderGameObject = GameObject.Find(nameof(WebPinataUploader));
var webFileUploader = webUploaderGameObject != null
? webUploaderGameObject.GetComponent<WebUploader>()
: new GameObject(nameof(WebUploader)).AddComponent<WebUploader>();
? webUploaderGameObject.GetComponent<WebPinataUploader>()
: new GameObject(nameof(WebPinataUploader)).AddComponent<WebPinataUploader>();

JsInitFileLoader(
webFileUploader.PinataCredentials = new PinataCredentials(apiKey);

JsInitPinataUploader(
callbackObjectName,
callbackMethodName,
webFileUploader.ApiUrl,
webFileUploader.ApiKey);
webFileUploader.PinataCredentials.ApiUrl,
webFileUploader.PinataCredentials.ApiKey);

return webFileUploader;
}

@@ -48,7 +53,7 @@ public static void RequestFile(Action<string> callback, string extensions)
JsRequestUserFile(extensions);
_responseCallback = callback;
}

public static void SetResult(string response)
{
var ipfsResponse = JsonSerializer.Deserialize<IpfsResponse>(response);
@@ -62,7 +67,7 @@ private static void Dispose()
}

[DllImport("__Internal")]
private static extern void JsInitFileLoader(
private static extern void JsInitPinataUploader(
string objectName,
string methodName,
string apiUrl,
29 changes: 29 additions & 0 deletions Runtime/Scripts/FileUploaders/JSFileUploader.jslib
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
mergeInto(LibraryManager.library, {
JsInitPinataUploader: function (
callbackObjectName,
callbackMethodName,
apiUrl,
apiKey
) {
InitIpfsUploader({
CallbackObjectName: UTF8ToString(callbackObjectName),
CallbackMethodName: UTF8ToString(callbackMethodName),
ApiUrl: UTF8ToString(apiUrl),
ApiKey: UTF8ToString(apiKey),
});
},

JsInitBase64Uploader: function (
callbackObjectName,
callbackMethodName
) {
InitBase64Uploader({
CallbackObjectName: UTF8ToString(callbackObjectName),
CallbackMethodName: UTF8ToString(callbackMethodName)
});
},

JsRequestUserFile: function (extensions) {
FileUploader.RequestUserFile(UTF8ToString(extensions));
},
});
3 changes: 3 additions & 0 deletions Runtime/Scripts/FileUploaders/OnChain.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions Runtime/Scripts/FileUploaders/OnChain/EditorBase64Uploader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#if UNITY_EDITOR
using System;
using System.Collections;
using System.IO;
using UnityEditor;


namespace TezosSDK.Scripts.FileUploaders.OnChain
{
public class EditorBase64Uploader : BaseUploader, IBaseUploader
{
public IEnumerator UploadFile(Action<string> callback)
{
yield return null;
var imagePath = EditorUtility.OpenFilePanel(
"Select image",
string.Empty,
SupportedFileExtensions
.Replace(".", string.Empty)
.Replace(" ", string.Empty)
);
callback.Invoke(ConvertImageToBase64(imagePath));
}

private static string ConvertImageToBase64(string imagePath)
{
var fileExtension = Path
.GetExtension(imagePath)
.Replace(".", string.Empty)
.ToLower();

var imageBytes = File.ReadAllBytes(imagePath);
var base64String = Convert.ToBase64String(imageBytes);
return $"data:image/{fileExtension};base64,{base64String}";
}
}
}
#endif

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 69 additions & 0 deletions Runtime/Scripts/FileUploaders/OnChain/WebBase64Uploader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System;
using System.Collections;
using System.Runtime.InteropServices;
using Logger = TezosSDK.Helpers.Logger;
using UnityEngine;

namespace TezosSDK.Scripts.FileUploaders.OnChain
{
public class WebBase64Uploader : BaseUploader, IBaseUploader
{
public void FileRequestCallback(string path)
{
WebBase64UploaderHelper.SetResult(path);
}

public IEnumerator UploadFile(Action<string> callback)
{
yield return null;
WebBase64UploaderHelper.RequestFile(callback, SupportedFileExtensions);
}
}

public static class WebBase64UploaderHelper
{
private static Action<string> _responseCallback;

public static IBaseUploader GetUploader()
{
const string callbackObjectName = nameof(WebBase64Uploader);
const string callbackMethodName = nameof(WebBase64Uploader.FileRequestCallback);

var webUploaderGameObject = GameObject.Find(nameof(WebBase64Uploader));
var uploader = webUploaderGameObject != null
? webUploaderGameObject.GetComponent<WebBase64Uploader>()
: new GameObject(nameof(WebBase64Uploader)).AddComponent<WebBase64Uploader>();

JsInitBase64Uploader(
callbackObjectName,
callbackMethodName);

return uploader;
}

public static void RequestFile(Action<string> callback, string extensions)
{
JsRequestUserFile(extensions);
_responseCallback = callback;
}

public static void SetResult(string response)
{
_responseCallback.Invoke(response);
Dispose();
}

private static void Dispose()
{
_responseCallback = null;
}

[DllImport("__Internal")]
private static extern void JsInitBase64Uploader(
string objectName,
string methodName);

[DllImport("__Internal")]
private static extern void JsRequestUserFile(string extensions);
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions Runtime/Scripts/FileUploaders/UploaderFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using TezosSDK.Scripts.FileUploaders.IPFS;
using TezosSDK.Scripts.FileUploaders.OnChain;
using UnityEngine;

namespace TezosSDK.Scripts.FileUploaders
{
public static class UploaderFactory
{
/// <summary>
/// Cross-platform image uploader to IPFS network via Pinata service.
/// </summary>
/// <param name="apiKey">API key from https://app.pinata.cloud/developers/api-keys</param>
public static IBaseUploader GetPinataUploader(string apiKey)
{
IPinataUploader uploader = null;

#if UNITY_WEBGL && !UNITY_EDITOR
uploader = WebPinataUploaderHelper.GetUploader(apiKey);
#elif UNITY_EDITOR
var editorUploaderGameObject = GameObject.Find(nameof(EditorPinataUploader));
uploader = editorUploaderGameObject != null
? editorUploaderGameObject.GetComponent<EditorPinataUploader>()
: new GameObject(nameof(EditorPinataUploader)).AddComponent<EditorPinataUploader>();
uploader.PinataCredentials = new PinataCredentials(apiKey);
#endif
return uploader;
}

public static IBaseUploader GetOnchainUploader()
{
IBaseUploader uploader = null;

#if UNITY_WEBGL && !UNITY_EDITOR
uploader = WebBase64UploaderHelper.GetUploader();
#elif UNITY_EDITOR
var editorUploaderGameObject = GameObject.Find(nameof(EditorBase64Uploader));
uploader = editorUploaderGameObject != null
? editorUploaderGameObject.GetComponent<EditorBase64Uploader>()
: new GameObject(nameof(EditorBase64Uploader)).AddComponent<EditorBase64Uploader>();
#endif
return uploader;
}
}
}
19 changes: 0 additions & 19 deletions Runtime/Scripts/IpfsUploader/BaseUploader.cs

This file was deleted.

20 changes: 0 additions & 20 deletions Runtime/Scripts/IpfsUploader/IFileUploader.cs

This file was deleted.

3 changes: 0 additions & 3 deletions Runtime/Scripts/IpfsUploader/IFileUploader.cs.meta

This file was deleted.

19 changes: 0 additions & 19 deletions Runtime/Scripts/IpfsUploader/JSFileUploader.jslib

This file was deleted.

26 changes: 0 additions & 26 deletions Runtime/Scripts/IpfsUploader/UploaderFactory.cs

This file was deleted.

2 changes: 1 addition & 1 deletion Runtime/Scripts/Tezos/API/Models/TokenContract.cs
Original file line number Diff line number Diff line change
@@ -206,7 +206,7 @@ private void DeployCompleted(string response)

var lastUsedContract = tokenContracts.Last();
Address = lastUsedContract.Address;
PlayerPrefs.SetString("CurrentContract", lastUsedContract.Address);
PlayerPrefs.SetString("CurrentContract:" + creator, lastUsedContract.Address);
OnDeployCompleted.Invoke(lastUsedContract.Address);
},
creator,
8 changes: 6 additions & 2 deletions Samples~/Scripts/DemoExample/Core/ExampleManager.cs
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
using Netezos.Encoding;
using TezosSDK.Beacon;
using TezosSDK.Helpers;
using TezosSDK.Scripts.FileUploaders;
using TezosSDK.Scripts.IpfsUploader;
using TezosSDK.Tezos;
using TezosSDK.Tezos.API.Models;
@@ -397,11 +398,14 @@ public void ChangeContract(string activeContractAddress)

public void UploadToIpfs()
{
var uploader = UploaderFactory.GetPinataUploader();
var uploader = UploaderFactory.GetOnchainUploader();

CoroutineRunner
.Instance
.StartWrappedCoroutine(uploader.UploadFile(ipfsResponse => { Logger.LogDebug($"Link to uploaded file: https://ipfs.io/ipfs/{ipfsResponse}"); }));
.StartWrappedCoroutine(uploader.UploadFile(ipfsResponse =>
{
Logger.LogDebug($"Link to uploaded file: {ipfsResponse}");
}));
}

public void GetCoins()
2 changes: 1 addition & 1 deletion WebGLFrontend/output/StreamingAssets/webgl-frontend.js

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions WebGLFrontend/src/FileUploaders.meta
33 changes: 33 additions & 0 deletions WebGLFrontend/src/FileUploaders/Base64Uploader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import BaseFileUploader from "./BaseFileUploader";

class Base64Uploader extends BaseFileUploader {
async FileReceived(file: File) {
window.unityInstance.SendMessage(
this.Config.CallbackObjectName,
this.Config.CallbackMethodName,
await this.СonvertImageToBase64(file)
);
}

СonvertImageToBase64(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();

reader.onloadend = () => {
if (typeof reader.result === "string") {
resolve(reader.result);
} else {
reject(new Error("Failed to convert image to base64."));
}
};

reader.onerror = (error) => {
reject(error);
};

reader.readAsDataURL(file);
});
}
}

export default Base64Uploader;
7 changes: 7 additions & 0 deletions WebGLFrontend/src/FileUploaders/Base64Uploader.ts.meta
53 changes: 53 additions & 0 deletions WebGLFrontend/src/FileUploaders/BaseFileUploader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { BaseFileUploaderType, BaseUploaderConfig } from "./Types";

abstract class BaseFileUploader implements BaseFileUploaderType {
FileUploaderDomElement: HTMLInputElement;
Config: BaseUploaderConfig;

Init(config: BaseUploaderConfig) {
this.Config = config;

this.FileUploaderDomElement = document.getElementById(
"fileuploader"
) as HTMLInputElement;

if (!this.FileUploaderDomElement) {
this.FileUploaderDomElement = document.createElement("input");
this.FileUploaderDomElement.setAttribute("style", "display:none;");
this.FileUploaderDomElement.setAttribute("type", "file");
this.FileUploaderDomElement.setAttribute("id", "fileuploader");
this.FileUploaderDomElement.setAttribute("class", "nonfocused");
document
.getElementsByTagName("body")[0]
.appendChild(this.FileUploaderDomElement);

this.FileUploaderDomElement.onchange = (event: Event) => {
const { files }: HTMLInputElement = event.target as HTMLInputElement;

if (files.length === 0) {
this.ResetFileUploader();
} else {
this.FileReceived(files[0]);
}
};
}
}

abstract FileReceived(file: File): void;

ResetFileUploader() {
this.FileUploaderDomElement?.setAttribute("class", "nonfocused");
}

RequestUserFile(fileExtensions: string) {
if (this.FileUploaderDomElement === null) this.Init(this.Config);

if (fileExtensions !== null || fileExtensions.match(/^ *$/) === null)
this.FileUploaderDomElement.setAttribute("accept", fileExtensions);

this.FileUploaderDomElement.setAttribute("class", "focused");
this.FileUploaderDomElement.click();
}
}

export default BaseFileUploader;
7 changes: 7 additions & 0 deletions WebGLFrontend/src/FileUploaders/BaseFileUploader.ts.meta
44 changes: 44 additions & 0 deletions WebGLFrontend/src/FileUploaders/IpfsUploader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { IpfsUploaderConfig, IpfsUploaderType } from "./Types";

import BaseFileUploader from "./BaseFileUploader";

class IpfsUploader extends BaseFileUploader implements IpfsUploaderType {
Config: IpfsUploaderConfig;

Init(config: IpfsUploaderConfig) {
super.Init(config);
this.Config = config;
}

async FileReceived(file: File) {
const formData = new FormData();
formData.append("file", file, file.name);
const options = {
method: "POST",
body: formData,

headers: {
Authorization: `Bearer ${this.Config.ApiKey}`,
},
};

try {
const request = await fetch(this.Config.ApiUrl, options);
const data: string = await request.text();

window.unityInstance.SendMessage(
this.Config.CallbackObjectName,
this.Config.CallbackMethodName,
data
);
} catch (error) {
console.error(
`Error during uploading file to ${this.Config.ApiUrl}\n${error}`
);
}

this.ResetFileUploader();
}
}

export default IpfsUploader;
37 changes: 37 additions & 0 deletions WebGLFrontend/src/FileUploaders/Types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
interface IpfsUploaderType extends BaseFileUploaderType {
Config: IpfsUploaderConfig;
Init(config: IpfsUploaderConfig): void;
}

interface IpfsUploaderConfig extends BaseUploaderConfig {
ApiUrl: string;
ApiKey: string;
}

interface IpfsResponse {
IpfsHash: string;
PinSize: number;
Timestamp: Date;
isDuplicate: boolean;
}

interface BaseFileUploaderType {
FileUploaderDomElement: HTMLInputElement;
Config: BaseUploaderConfig;
Init(config: BaseUploaderConfig): void;
RequestUserFile(fileExtensions: string): void;
ResetFileUploader(): void;
}

interface BaseUploaderConfig {
CallbackObjectName: string;
CallbackMethodName: string;
}

export {
BaseFileUploaderType,
BaseUploaderConfig,
IpfsResponse,
IpfsUploaderConfig,
IpfsUploaderType,
};
80 changes: 0 additions & 80 deletions WebGLFrontend/src/IpfsUploader/IpfsUploader.ts

This file was deleted.

23 changes: 0 additions & 23 deletions WebGLFrontend/src/IpfsUploader/Types.ts

This file was deleted.

41 changes: 28 additions & 13 deletions WebGLFrontend/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import BeaconWallet from './WalletProviders/Beacon';
import IpfsUploader from './IpfsUploader/IpfsUploader';
import KukaiWallet from './WalletProviders/Kukai';
import { FileUploader, FileUploaderConfig } from './IpfsUploader/Types';
import { Wallet, WalletType } from './WalletProviders/Types';
import {
BaseFileUploaderType,
BaseUploaderConfig,
IpfsUploaderConfig,
IpfsUploaderType,
} from "./FileUploaders/Types";
import { Wallet, WalletType } from "./WalletProviders/Types";

import Base64Uploader from "./FileUploaders/Base64Uploader";
import IpfsUploader from "./FileUploaders/IpfsUploader";
import BeaconWallet from "./WalletProviders/Beacon";
import KukaiWallet from "./WalletProviders/Kukai";

let cachedKukaiWallet: KukaiWallet;
let cachedBeqaconWallet: BeaconWallet;
@@ -25,16 +32,23 @@ function InitWalletProvider(
window.WalletProvider.SetNetwork(networkName, rpcUrl);
}

function InitFileUploader(config: FileUploaderConfig) {
if (window.FileUploader) return;
const ipfsUploader: FileUploader = new IpfsUploader();
ipfsUploader.InitFileUploader(config);
function InitIpfsUploader(config: IpfsUploaderConfig) {
if (window.FileUploader instanceof IpfsUploader) return;

const uploader: IpfsUploaderType = new IpfsUploader();
uploader.Init(config);
window.FileUploader = uploader;
}

window.FileUploader = ipfsUploader;
function InitBase64Uploader(config: BaseUploaderConfig) {
const uploader = new Base64Uploader();
uploader.Init(config);
window.FileUploader = uploader;
}

window.InitWalletProvider = InitWalletProvider;
window.InitFileUploader = InitFileUploader;
window.InitIpfsUploader = InitIpfsUploader;
window.InitBase64Uploader = InitBase64Uploader;

declare global {
interface Window {
@@ -45,7 +59,8 @@ declare global {
rpcUrl: string,
walletType: WalletType
): void;
InitFileUploader(config: FileUploaderConfig): void;
FileUploader: FileUploader | null;
InitIpfsUploader(config: IpfsUploaderConfig): void;
InitBase64Uploader(config: BaseUploaderConfig): void;
FileUploader: BaseFileUploaderType | null;
}
}

0 comments on commit 104de63

Please sign in to comment.