UNITON CONNECT is a user-friendly solution for working with the TON ecosystem inside web applications on Unity.
- Connecting TON wallets through the native window that Telegram users are used to,
- Executing transactions via Toncoin,
- Reading wallet balance (as long as Toncoin is available),
- Retrieving NFT collections from a connected wallet,
- Filtering of loaded nft collections by various filters: skam, collection address and so on,
- Conversion of wallet addresses into different formats and their visualization.
- Reading balance of basic (GRAM, NOT, DOGS) and custom jettons (by wallet master address),
- Sending basic and custom jettons,
- Sending NFTs from available collections on the connected wallet,
- Swapping custom and basic jettons to toncoin and reverse,
- Creating and mint of custom jettons,
- Creating and mint NFT collections.
You can test the SDK without installation on a demo app in your browser or directly in the TMA (Telegram Mini App).
Wallet Provider | WebGL Desktop | WebGL Mobile |
---|---|---|
Telegram Wallet | ✔️ | ✔️ |
Ton Keeper | ✔️ | ✔️ |
My Ton Wallet | ✔️ | ✔️ |
Ton Hub | ||
DeWallet (TMA) | ||
Bitget Wallet | ✔️ | ✔️ |
Bitget Web3 (TMA) | ✔️ | |
Safe Pal Wallet | ||
OKX Wallet | ✔️ | ✔️ |
OKX Mini Wallet (TMA) | ||
Hot Wallet (TMA) | ❌ | ❌ |
Bybit Wallet | ✔️ | ✔️ |
Gate Wallet | ❌ | |
Binance Web3 Wallet | ✔️ | |
Fintopio Wallet (TMA) | ✔️ | ✔️ |
Open Mask (Web Extension) | ✔️ | ❌ |
XTon Wallet (Web Extension) | ✔️ | ❌ |
Ton Wallet (Web Extension) | ✔️ | ❌ |
✔️ Supported ❌ Not Supported
Wallet Provider | QR Code | Deeplink |
---|---|---|
Telegram Wallet | 💻+📱 | 💻+📱 |
Ton Keeper | 💻+📱 | 💻+📱 |
My Ton Wallet | 💻+📱 | 💻+📱 |
Ton Hub | 💻+📱 | 📱 |
DeWallet (TMA) | ❌ | 💻+📱 |
Bitget Wallet | 💻+📱 | 💻+📱 |
Bitget Web3 (TMA) | ❌ | 💻+📱 |
Safe Pal Wallet | ❌ | 💻+📱 |
OKX Wallet | 💻+📱 | 💻+📱 |
OKX Mini Wallet (TMA) | ❌ | 💻+📱 |
Hot Wallet (TMA) | ❌ | ❌ |
Bybit Wallet | 💻+📱 | 💻+📱 |
Gate Wallet | ❌ | 📱 |
Binance Web3 Wallet | 💻+📱 | 📱 |
Fintopio Wallet (TMA) | 💻+📱 | 💻+📱 |
Open Mask (Web Extension) | ❌ | 💻 |
XTon Wallet (Web Extension) | ❌ | 💻 |
Ton Wallet (Web Extension) | ❌ | 💻 |
💻+📱 All Clients 💻 Desktop Client 📱 Mobile Client ❌ Not Supported
Token | Status | Func |
---|---|---|
TON | ✔️ | Balance, Send |
NOT | ||
GRAM | ||
DOGS | ||
NFT | ✔️ | Balance, Filter |
Custom Jetton |
✔️ Supported ❌ Not Supported
For the library to work correctly, the following dependencies must be installed in the project before use:
- WebGL Threading Patcher allows you to run asynchronous operations in a single thread in WebGL builds. Initially they do not work due to lack of multithreading support in them,
- Newtonsoft - modern solution for convenient work with json files.
This section is for smooth migration between sdk versions, in case of a global API change.
Download the latest version of the SDK via the .unityPackage file here.
Before you can use all the features of the SDK, you must initialize it in one of two available ways.
The UnitonConnectSDK
component has an option called Initialize On Awake
. When you activate it, the SDK will initialize automatically. You only need to subscribe to the necessary events and start working with it.
Below is a test example of how it can look like.
public sealed class InitExample: MonoBehaviour
{
private UnitonConnectSDK _unitonConnect;
private void OnDisable()
{
_unitonConnect.OnNativeInitialized -= SdkInitialized;
}
private void Start()
{
_unitonConnect = UnitonConnectSDK.Instance;
_unitonConnect.OnNativeInitialized += SdkInitialized;
_unitonConnect.Initialize();
}
private void SdkInitialized(bool isSuccess)
{
if (isSuccess)
{
Debug.Log("Sdk has been successfully initialized, " +
"you can test the functionality ^-^");
}
}
}
At this point, you may encounter errors because your dApp application has not yet been configured.
If you just want to test the SDK, activate the Test Mode
option of the UnitonConnectSDK
component. In this case, the SDK will initialize the library's test application.
In case you want your application name, its logo and a link to the project itself to be displayed when connecting to the wallets. You need to enter these data in the dApp Config
window, which is located at the Uniton Connect -> dApp Config
path.
Here you need to select your game/application logo, enter a title and provide a link to the site where it will be published.
IMPORTANT: Starting with version 0.2.8
, you need to provide a link to your own API server, which uploads NFT collection images bypassing CORS
and converts from webP
to jpeg
format (png format is available, but its size will take longer to load).
To raise your own API server on Node.js
, go to the Backend Set Up section.
Now you need to do the first build of the project to generate the application configuration from the editor to a json file.
Go to Build to customize the build settings.
After the first build and publishing the project to Github Pages
or another test server
, you can continue working with the SDK without any problem if you followed the second method.
Now it's time for some examples of how to use the Uniton Connect
library API.
All code available for use in the library is fully documented. If you have any questions when working with the library API,
you can always see the implementation of all available functions in the Example scene
.
Now we need to add callbacks to get the connection status of the wallet in the app.
public sealed class ConnectWalletExample: MonoBehaviour
{
[SerializeField, Space] private Button _connectButton;
private UnitonConnectSDK _unitonConnect;
private void OnDisable()
{
_connectButton.onClick.RemoveListener(Connect);
_unitonConnect.OnNativeInitialized -= SdkInitialized;
_unitonConnect.OnNativeWalletConnectionFinished -= WalletConnectionFinished;
_unitonConnect.OnNativeWalletConnectionFailed -= WalletConnectionFailed;
}
private void Start()
{
_unitonConnect = UnitonConnectSDK.Instance;
_connectButton.interactable = false;
_connectButton.onClick.AddListener(Connect);
_unitonConnect.OnNativeInitialized += SdkInitialized;
_unitonConnect.OnNativeWalletConnectionFinished += WalletConnectionFinished;
_unitonConnect.OnNativeWalletConnectionFailed += WalletConnectionFailed;
}
private void Connect()
{
if (!_unitonConnect.IsInitialized)
{
Debug.LogWarning("Sdk is not initialized, connection canceled");
return;
}
_unitonConnect.Connect();
}
private void SdkInitialized(bool isSuccess)
{
_connectButton.interactable = isSuccess;
}
private void WalletConnectionFinished(NewWalletConfig wallet)
{
var userAddress = wallet.Address;
var successConnectMessage = $"Wallet is connected, " +
$"Address: {WalletConnectUtils.GetNonBounceableAddress(userAddress), \n}" +
$"Public Key: {wallet.PublicKey}";
var shortAddress = WalletVisualUtils.ProcessWalletAddress(userAddress, 6);
Debug.Log(successConnectMessage);
Debug.Log($"Parsed short address: {shortAddress}");
}
private void WalletConnectionFailed(string errorMessage)
{
Debug.LogError("Failed to connect wallet, reason: {errorMessage}");
}
}
P.S: Previously it was necessary to work with the type of connection to the wallet manually, determining the presence of this or that bridge in the loaded configuration. Since version 0.2.9.5, all connection is done through a native window! Now you don't need to make connection windows, create wallets icon for connection - all this is handled by native JS SDK.
After clicking on the button and calling the Connect()
method, a native window will open, displaying the wallets available for connection (depending on whether the web application is running on a PC or phone, their number will vary).
Once the selected wallet is successfully connected, you can beautifully display its address. The SDK has a method WalletVisualUtils.ProcessWalletAddress(string address, int value)
that shows only the first and last characters of the address.
P.S: Starting from version 0.2.8
, you can change the address format of a connected TON wallet.
Conversion to HEX/RAW
format:
string baseAddress = "UQDB2p0iHYcDK3Yq1kdliitRFaOK9LIynUgk-yXLZXmc2V5I";
string hexAddress = WalletConnectUtils.GetHEXAddress(baseAddress);
// OR
string currentAddress = UnitonConnectSDK.Istance.Wallet.ToString();
string hexAddress = UnitonConnectSDK.Instance.Wallet.ToHex();
//result: 0:c1da9d221d87032b762ad647658a2b5115a38af4b2329d4824fb25cb65799cd9
Conversion to Bounceable
format:
string baseAddress = "UQDB2p0iHYcDK3Yq1kdliitRFaOK9LIynUgk-yXLZXmc2V5I";
string bounceableAddress = WalletConnectUtils.GetBounceableAddress(baseAddress);
// OR
string hexAddress = UnitonConnectSDK.Instance.Wallet.ToBounceable();
//result: EQDB2p0iHYcDK3Yq1kdliitRFaOK9LIynUgk+yXLZXmc2QON
Convert to Non Bounceable
format:
string baseAddress = "EQDB2p0iHYcDK3Yq1kdliitRFaOK9LIynUgk+yXLZXmc2QON";
string nonBounceableAddress = WalletConnectUtils.GetNonBounceableAddress(baseAddress);
// OR
string hexAddress = UnitonConnectSDK.Instance.Wallet.ToNonBounceable();
//result: UQDB2p0iHYcDK3Yq1kdliitRFaOK9LIynUgk-yXLZXmc2V5I
IMPORTANT: UnitonConnectSDK has an option that automatically restores the last saved wallet session. You can subscribe to the result of this event UnitonConnectSDK.OnNativeWalletConnectionRestored
and handle the result via the boolean isRestored
.
At the moment in version 0.2.8
, from the list of interactions with the wallet there is only sending Toncoin
to the desired address.
Therefore, below we will show an example of implementing only this function.
P.S: When the wallet functionality in SDK Uniton Connect
is updated, the examples in the documentation will be updated.
public sealed class TransactionSendingExample: MonoBehaviour
{
[SerializeField, Space] private Button _sendTransctionButton;
private UnitonConnectSDK _unitonConnect;
private string _latestTransactionHash;
private void OnDisable()
{
_unitonConnect.OnNativeSendingTonFinished -= TransactionSendingFinished;
_unitonConnect.OnNativeTransactionConfirmed -= TonTransactionConfirmed;
_sendTransctionButton.onClick.RemoveListener(Send);
}
private void Start()
{
_unitonConnect = UnitonConnectSDK.Instance;
_unitonConnect.OnNativeSendingTonFinished += TransactionSendingFinished;
_unitonConnect.OnNativeTransactionConfirmed += TonTransactionConfirmed;
_sendTransctionButton.onClick.AddListener(Send);
}
private void Send()
{
if (!_unitonConnect.IsWalletConnected)
{
Debug.LogWarning("Wallet was not connected");
return;
}
_unitonConnect.SendTransaction(ClassicTokenTypes.Toncoin,
"EQDPwEk-cnQXEfFaaNVXywpbKACUMwVRupkgWjhr_f4UrpH_",
(double)10.0f, "Ton Foundation is scam!");
}
private void TransactionSendingFinished(string transactionHash)
{
_latestTransactionHash = transactionHash;
Debug.Log($"Ton transaction sended, hash: {transactionHash}");
}
private void TonTransactionConfirmed(
SuccessTransactionData transactionData)
{
Debug.Log($"Ton transaction {_latestTransactionHash} " +
$"confirmed with status: {transactionData.IsSuccess}");
var status = transactionData.IsSuccess;
var newBalance = transactionData.EndBalance.FromNanoton();
var fee = transactionData.TotalFees.FromNanoton();
var sendedAmount = transactionData.OutMessages[0].Value.FromNanoton();
var recipientAddress = transactionData.OutMessages[0].Recipient.Address;
var convertedAddress = WalletConnectUtils.GetNonBounceableAddress(recipientAddress);
var message = transactionData.OutMessages[0].DecodedBody.MessageText;
var transactionDetails = $"Loaded transaction data: \n" +
$"STATUS: {transactionData.IsSuccess},\n" +
$"HASH: {_latestTransactionHash},\n" +
$"NEW BALANCE: {newBalance} TON,\n" +
$"FEE: {fee} TON,\n" +
$"SENDED AMOUNT: {sendedAmount} TON,\n" +
$"RECIPIENT ADDRESS: {convertedAddress},\n" +
$"MESSAGE: {message}";
Debug.Log(transactionDetails);
}
}
This example shows a test implementation of sending toncoins to my TON address.
In the UnitonConnectSDK.Instance.SendTransaction()
method it is necessary to pass the recipient address, the number of TON in double
and the transaction comment (optionally, you can not use it and send without it - the SDK provides it).
If the transaction is successful, the OnNativeSendingTonFinished
event will be called, where you can get its hash, which is parsed from Boc, which is passed to the native sdk.
In case the transaction failed to be sent, the OnNativeTransactionSendingFailed
event will be called, where you can get a potential reason for the failed transaction.
P.S: to actually confirm the sending of the toncoin to the recipient's address, automatic processing of the transaction status in the blockchain has been added.
To get a detailed status with all transaction information, subscribe to the OnNativeTransactionConfirmed
event.
IMPORTANT: transaction confirmation is done in real time
, based on a snapshot of the blockchain via the Ton API. The processing time depends on the speed of the TON blockchain. You can adjust the processing time yourself (standard delay is 15 seconds).
Starting with version 0.2.8
, the ability to obtain NFT collections from a connected wallet has been added.
Below you can see the implementation of downloading all NFT collections:
public sealed class LoadingNftsExample : MonoBehaviour
{
[SerializeField, Space] private Button _loadAllNftCollections;
[SerializeField] private Button _loadTargetNftCollection;
private UnitonConnectSDK _unitonConnect;
private UserAssets.NFT _nftStorage => _unitonConnect.UserAssets.Nft;
private void Start()
{
_unitonConnect = UnitonConnectSDK.Instance;
_nftStorage.OnNftCollectionsClaimed += NftCollectionsClaimed;
_nftStorage.OnTargetNftCollectionClaimed += TargetNftCollectionClaimed;
_nftStorage.OnNftCollectionsNotFounded += NftCollectionsNotFounded;
_loadAllNftCollections.onClick.AddListener(LoadAll);
_loadTargetNftCollection.onClick.AddListener(LoadTarget);
}
private void OnDestroy()
{
_nftStorage.OnNftCollectionsClaimed -= NftCollectionsClaimed;
_nftStorage.OnTargetNftCollectionClaimed -= TargetNftCollectionClaimed;
_nftStorage.OnNftCollectionsNotFounded -= NftCollectionsNotFounded;
_loadAllNftCollections.onClick.RemoveListener(LoadAll);
_loadTargetNftCollection.onClick.RemoveListener(LoadTarget);
}
private void LoadAll()
{
_nftStorage.Load(10);
}
private void LoadTarget()
{
//Address of Lost Dogs collection
string collectionAddress = "EQAl_hUCAeEv-fKtGxYtITAS6PPxuMRaQwHj0QAHeWe6ZSD0"
_nftStorage.LoadTargetCollection(collectionAddress, 10);
}
private async void NftCollectionsClaimed(NftCollectionData collections)
{
if (collections.Items.Count == 0)
{
Debug.LogWarning("No NFT collections was found on the wallet");
return;
}
List<NftViewData> nftVisual = new();
foreach (var nft in collections.Items)
{
var iconUrl = nft.Get100x100ResolutionWebp();
Debug.Log($"Claimed icon by urL: {iconUrl}");
var nftIcon = await WalletVisualUtils.GetIconFromProxyServerAsync(iconUrl);
var nftName = nft.Metadata.ItemName;
var newNftView = new NftViewData()
{
Icon = nftIcon,
Name = nftName
};
nftVisual.Add(newNftView);
Debug.Log($"Created NFT view with name: {nftName}");
}
}
private void TargetNftCollectionClaimed(NftCollectionData collection)
{
Debug.Log($"Loaded target nft collection:{collection.Items.Collection.Name}");
}
private void NftCollectionsNotFounded()
{
Debug.LogWarning("Nft collections not found");
}
}
IMPORTANT: To download images from NFT collections, you cannot directly access the repository links because each collection has its own servers configured.
So if you try to load a collection unsuccessfully, you will get an empty image due to CORS blocking the request.
To do this, you need to call the await WalletVisualUtils.GetIconFromProxyServerAsync(iconUrl)
method, which calls your API server, which downloads the image from the source and gives it to your Unity client.
P.S: In addition, when you attempt to load webP images, the server performs conversion to JPEG format
.
If you try to upload a JPEG/PNG
, the image will be returned with the original format.
Before you can upload a picture of an item from the NFT collection, you must select an image format.
private async void NftCollectionsClaimed(NftCollectionData nftCollections)
{
var firstItem = collections.Items[0];
string bestIconUrl = firstItem.GetBestResolutionPng();
string littleIconUrl = firstItem.Get5x5ResolutionWebp();
string smallIconUrl = firstItem.Get100x100ResolutionWebp();
string mediumIconUrl = firstItem.Get500x500ResolutionWebp();
string bigIconUrl = firstItem.Get1500x1500ResolutionWebp();
}
P.S: The method names reflect the size of the webp image in pixels.
Starting with version 0.2.8
, added possibility to get current balance of connected wallet (only Toncoin at the moment).
Implementation of current balance request is shown below:
public sealed class TonBalanceLoadingExample: MonoBehaviour
{
[SerializeField, Space] private TextMeshProUGUI _balanceBar;
private UnitonConnectSDK _unitonConnect;
private void OnDisable()
{
_unitonConnect.OnTonBalanceClaimed -= TonBalanceClaimed;
}
private void Start()
{
_unitonConnect = UnitonConnectSDK.Instance;
if (!_unitonConnect.IsWalletConnected)
{
Debug.LogWarning("Wallet is not connected");
return;
}
_unitonConnect.OnTonBalanceClaimed += TonBalanceClaimed;
_unitonConnect.LoadBalance(ClassicTokenTypes.Toncoin);
}
private void TonBalanceClaimed(decimal balance)
{
Debug.Log($"Loaded ton balance: {balance}");
_balanceBar.text = $"{balance} TON";
}
}
If you need to transfer your Ton balance to Nanoton and reverse, you can use the following methods:
private void TonBalanceClaimed(decimal tonBalance)
{
decimal nanotons = tonBalance.ToNanoton();
decimal tons = nanotons.FromNanoton()
Debug.Log($"Loaded TON balance: {tonBalance}");
Debug.Log($"Loaded TON balance in nanotons: {nanotons}");
_balanceBar.text = $"{tonBalance} TON";
}
In order to build a project, you must first configure several settings in the Player Settings
window:
- Set the custom
Uniton
build template, which is available after importing the library into the project. It can be set underBuild Settings -> Player Settings -> Resolution and Presentation -> WebGL Template
, - Then you need to switch the
Managed Stripping Level
property type to Minimal, so that the library functionality is not cut out when building the uniton and works correctly, - Now the final touches, under
Player Settings -> Publish Settings
you need to switch theEnable Exception
property to any value exceptExplicitly Thrown Exceptions Only
. Because if build errors occur, you can freeze or even crash the project.
After a successful build, 2 files will be created in the build directory: icon.png
and dAppData.json
. These will contain all the information you entered earlier in the dApp Config
window.
You can now publish your project anywhere you want. After publishing your project, go back to the dApp Config
window and specify the correct link so that the SDK will work correctly with your project.
For test mode I recommend using Github Actions
with their Static Page
feature. A guide to deploying a WebGL build to Unity can be found online, so there's no need to describe it here.
First, you need to download the source code of this Proxy Server, which the SDK accesses to load and convert pictures from NFT collections:
https://github.com/MrVeit/Veittech-UnitonConnect-ServerAPI
If you already have Node.js installed on your Windows computer (does anyone make Unity games on Linux? :D), you can skip this step and move on to the next one. If you still don't have it installed, you need to go to the official Node.js website and install it yourself.
After installing and cloning the above two repositories, you can open the project in VS Code
or any other code editor
that supports Node.js.
Now, to be able to run the proxy locally and start testing, you need to create an environment variable repository. To do this, you need to create a file named .env
in the project directory, but without a file format.
The following information must be filled in for the Proxy Server environment variables repository:
HOST = http://localhost:
PORT = 3000
- Variable
HOST
is a link to your domain where the server is running, for testing purposes we will use the local addresshttp://localhost
, - Variable
PORT
is a free port, which will listen to the proxy server to receive and send requests to the unity game client.
You can now run a proxy server to download pictures from nft collections. Open a terminal in the code editor in which you opened the project and type the following command:
npm start
IMPORTANT: In case you encounter a startup problem at this stage, it means you don't have Node.js installed or it was installed incorrectly. Try reinstalling or searching for a solution to your problem on the Internet.
P.S: Now you can go back to the Unity project, open the dApp configuration window via Uniton Connect -> dApp Config
and fill the API Server URL
field with http://localhost:3000
.
Soon
Ton Wallet (TON/NOT/USDt):
UQDPwEk-cnQXEfFaaNVXywpbKACUMwVRupkgWjhr_f4Ursw6
Multichain Wallet (BTC/ETH/BNB/MATIC)
0x231803Df809C207FaA330646BB5547fD087FEcA1