-
Notifications
You must be signed in to change notification settings - Fork 5
Open
Description
Describe the feature or improvement you're requesting
Hey. Is this SDK supporting OwnedObjects as an argument? I am getting Unknow Call Arg Type error after I send owned object's id. Here Unity and Move codes :
module lucky_game::lucky_game
{
use sui::object::{Self, UID};
use sui::balance::{Self, Balance};
use sui::tx_context::{Self, TxContext};
use sui::transfer;
use sui::coin::{Self, Coin};
use sui::sui::SUI;
use sui::random::{Self, Random};
use std::hash;
use sui::event;
use std::vector;
public struct DiceValue has copy, drop
{
value: u8,
}
public struct Commit has key
{
id: UID,
player: address,
commit_hash: vector<u8>,
amount: u64,
input: u8,
}
public struct CHEST has key
{
id: UID,
chestBalance: Balance<SUI>,
owner: address,
}
const PUBLISHER: address = @0x0d9b5ca4ebae5f4a7bd3f17e4e36cd6f868d8f0c5a7f977f94f836631fe0288d;
public fun create(ctx: &mut TxContext)
{
assert!(tx_context::sender(ctx) == PUBLISHER, 100);
let chest = CHEST
{
id: object::new(ctx),
chestBalance: balance::zero(),
owner: ctx.sender(),
};
transfer::share_object(chest);
}
public fun topup(chest: &mut CHEST, mut coins: Coin<SUI>)
{
coin::put(&mut chest.chestBalance, coins);
}
public fun withdraw(chest: &mut CHEST, amount: u64, ctx: &mut TxContext)
{
assert!(tx_context::sender(ctx) == chest.owner, 1);
assert!(amount > 0, 6); // Sıfırdan büyük miktar kontrolü
assert!(chest.chestBalance.value() >= amount, 7); // Yeterli bakiye kontrolü
// Chest'ten belirtilen miktarı çek
let coin = coin::take(&mut chest.chestBalance, amount, ctx);
// Kullanıcıya gönder
transfer::public_transfer(coin, chest.owner);
}
/// Kullanıcı commit gönderir
public entry fun commit( chest: &mut CHEST, mut user_coin: Coin<SUI>, commit_hash: vector<u8>, input: u8, ctx: &mut TxContext)
{
let amount = coin::value(&user_coin);
assert!(amount >= 100_000_000, 2);
assert!(input >= 2 && input <= 8, 3);
// Coin'i chest'e koy
coin::put(&mut chest.chestBalance, user_coin);
let commit = Commit
{
id: object::new(ctx),
player: tx_context::sender(ctx),
commit_hash,
amount,
input,
};
transfer::transfer(commit, tx_context::sender(ctx));
}
/// Kullanıcı secret'ı reveal eder ve random sonucu hesaplanır
public entry fun reveal(r: &Random, chest: &mut CHEST, commit: Commit, secret: vector<u8>, ctx: &mut TxContext)
{
assert!(commit.player == tx_context::sender(ctx), 10);
// Hash doğrulama (SHA3-256 std::hash altındadır)
let expected_hash = hash::sha3_256(secret);
assert!(expected_hash == commit.commit_hash, 11);
// Random üretim: mix yok; doğrudan generator kullan
let mut generator = random::new_generator(r, ctx);
let result = random::generate_u8_in_range(&mut generator, 1, commit.input);
if (result != 1)
{
let input_u64 = commit.input as u64;
let mut factor = ((100000000 / (10000 - (10000 / input_u64))) - 10000) / 100;
factor = factor - 3;
let bonus = (commit.amount * factor) / 100;
// Balance kontrolü (doğru kullanım)
assert!(balance::value(&chest.chestBalance) >= bonus, 4);
// Ödeme
let pay_bonus = coin::take(&mut chest.chestBalance, bonus, ctx);
let mut refund = coin::take(&mut chest.chestBalance, commit.amount, ctx);
coin::join(&mut refund, pay_bonus);
transfer::public_transfer(refund, commit.player);
event::emit(DiceValue { value:result });
}
else
{
event::emit(DiceValue { value:result });
};
let Commit { id, player: _, commit_hash: _, amount: _, input: _ } = commit;
object::delete(id);
}
}
using Ali.Helper;
using NBitcoin;
using OpenDive.BCS;
using Org.BouncyCastle.Ocsp;
using SHA3.Net;
using Sui.Accounts;
using Sui.Rpc;
using Sui.Rpc.Client;
using Sui.Rpc.Models;
using Sui.Transactions;
using Sui.Types;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net.Sockets;
using System.Numerics;
using System.Security.Cryptography;
using System.Threading.Tasks;
using Unity.Mathematics;
using Unity.VisualScripting;
using UnityEditor.PackageManager;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UIElements;
public class SuiManager : GenericSingleton<SuiManager>
{
SuiClient _client;
Account _account;
[SerializeField] private string _deathCardPackageId = "";
[SerializeField] private string _deathCardChestId = "";
private string _deathCardModuleFunc = "::lucky_game::play";
private string _deathCardCommitFunc = "::lucky_game::commit";
private string _deathCardRevealFunc = "::lucky_game::reveal";
private string _randomPackageId = "0x8";
SuiStructTag _sui_coin = new SuiStructTag("0x2::sui::SUI");
SuiStructTag _coin = new SuiStructTag("0x2::coin::Coin");
[HideInInspector]
public UnityEvent OnDeathCardStarted = new UnityEvent();
[HideInInspector]
public UnityEvent<int> OnDeathCardEnded = new UnityEvent<int>();
[HideInInspector]
public UnityEvent<float> OnBalanceUpdated = new UnityEvent<float>();
[HideInInspector]
public UnityEvent<float> OnBalanceChanged = new UnityEvent<float>();
private void Start()
{
_client = new SuiClient(Constants.TestnetConnection);
_account = new Account("****");
//Debug.Log(_account.PrivateKey.KeyHex);
//Debug.Log(_account.SuiAddress().KeyHex);
CheckBalance();
Test();
}
async void Test()
{
//System.Guid guid = System.Guid.NewGuid();
//byte[] secret = guid.ToByteArray();
//HashAlgorithm halg = Sha3.Create();
//byte[] computedHash = halg.ComputeHash(secret);
//Debug.Log("Ok => " + guid.ToString());
//string commitAddress = await Commit(0.1m, 8, computedHash);
//await Reveal(commitAddress, secret);
System.Guid guid = new System.Guid("a8eb7e10-a909-4962-a69f-6d977646a1fa");
HashAlgorithm halg = Sha3.Create();
byte[] secret = guid.ToByteArray();
byte[] computedHash = halg.ComputeHash(secret);
await Reveal("0xe7bb117a7ab3f4091c1c12ac20b6961a788f43a0687e8ef0da8b0fc893834d0d", secret);
}
float GetFloatFromBigInteger(BigInteger value)
{
decimal suiValue = (decimal)value / 1_000_000_000m;
return (float)suiValue;
}
async Task CheckBalance()
{
RpcResult<Balance> result = await _client.GetBalanceAsync(_account);
BigInteger balance = result.Result.TotalBalance;
decimal suiBalance = (decimal)balance / 1_000_000_000m;
OnBalanceUpdated?.Invoke((float)suiBalance);
}
public async void DeathCard(float betAmount, byte cardCount)
{
OnDeathCardStarted?.Invoke();
int diceValue = await PlayDeathCard((decimal)betAmount, cardCount);
OnDeathCardEnded?.Invoke(diceValue);
//await CheckBalance();
}
async Task<List<CoinDetails>> GetSUICoins()
{
List<CoinDetails> result = new List<CoinDetails>();
RpcResult<CoinPage> alice_sui_coins = await _client.GetCoinsAsync(_account, _sui_coin);
for (int i = 0; i < alice_sui_coins.Result.Data.Length; i++)
{
result.Add(alice_sui_coins.Result.Data[i]);
}
return result;
}
async Task<string> Commit(decimal amount, byte cardCount, byte[] commitHash)
{
Debug.Log("Bet Amount => " + amount);
TransactionBlock tx_block = new TransactionBlock();
ulong requestedAmountLong = (ulong)(amount * 1_000_000_000m);
List<TransactionArgument> splitArgs = tx_block.AddMoveCallTx
(
SuiMoveNormalizedStructType.FromStr("0x2::coin::split"),
new SerializableTypeTag[] { new SerializableTypeTag("0x2::sui::SUI") },
new TransactionArgument[]
{
tx_block.gas, // Insert coin object ID here
tx_block.AddPure(new U64(requestedAmountLong)) // Insert split amount here
}
);
tx_block.AddMoveCallTx
(
SuiMoveNormalizedStructType.FromStr($"{_deathCardPackageId}{_deathCardCommitFunc}"),
new SerializableTypeTag[] { },
new TransactionArgument[]
{
tx_block.AddObjectInput(_deathCardChestId),
splitArgs[0],
tx_block.AddPure(new Bytes(commitHash)),
tx_block.AddPure(new U8(cardCount))
}
);
TransactionBlockResponseOptions transactionBlockResponseOptions = new TransactionBlockResponseOptions();
transactionBlockResponseOptions.ShowEvents = true;
transactionBlockResponseOptions.ShowBalanceChanges = true;
transactionBlockResponseOptions.ShowEffects = true;
transactionBlockResponseOptions.ShowObjectChanges = true;
RpcResult<TransactionBlockResponse> result_task = await _client.SignAndExecuteTransactionBlockAsync
(
tx_block,
_account,
transactionBlockResponseOptions
);
if (result_task.Error != null)
{
Debug.Log("PlayDeathCard Error => " + result_task.Error.Message);
return "";
}
else if(result_task.Result != null && result_task.Result.ObjectChanges != null)
{
for (int i = 0; i < result_task.Result.ObjectChanges.Length; i++)
{
ObjectChange oc = result_task.Result.ObjectChanges[i];
if(oc.Type == ObjectChangeType.Created)
{
Debug.Log(oc.Change.ToString());
return oc.Change.ToString();
}
}
}
return "";
}
async Task<int> Reveal(string commitAddress, byte[] secret)
{
TransactionBlock tx_block = new TransactionBlock();
tx_block.AddMoveCallTx
(
SuiMoveNormalizedStructType.FromStr($"{_deathCardPackageId}{_deathCardRevealFunc}"),
new SerializableTypeTag[] { new SerializableTypeTag("0xd83656ac7864ec1581b1cc2b0ee37f0e6e7b95a27a2edfe7fe2d6d14927b1f51::lucky_game::Commit") },
new TransactionArgument[]
{
tx_block.AddObjectInput(_randomPackageId),
tx_block.AddObjectInput(_deathCardChestId),
tx_block.AddObjectInput(commitAddress),
tx_block.AddPure(new Bytes(secret))
}
);
TransactionBlockResponseOptions transactionBlockResponseOptions = new TransactionBlockResponseOptions();
transactionBlockResponseOptions.ShowEvents = true;
transactionBlockResponseOptions.ShowBalanceChanges = true;
transactionBlockResponseOptions.ShowEffects = true;
transactionBlockResponseOptions.ShowObjectChanges = true;
Debug.Log(tx_block.Serialize().ToString());
RpcResult<TransactionBlockResponse> result_task = await _client.SignAndExecuteTransactionBlockAsync
(
tx_block,
_account,
transactionBlockResponseOptions
);
if (result_task.Error != null)
{
Debug.Log("Reveal Error => " + result_task.Error.Message);
return -1;
}
if (result_task.Result != null && result_task.Result.BalanceChanges != null && result_task.Result.BalanceChanges.Length > 0)
{
BigInteger changeAmountBig = result_task.Result.BalanceChanges[0].Amount;
float changeAmount = GetFloatFromBigInteger(changeAmountBig);
OnBalanceChanged?.Invoke(GetFloatFromBigInteger(result_task.Result.BalanceChanges[0].Amount));
}
try
{
foreach (var m_event in result_task.Result.Events)
{
if (m_event.Type.Contains("DiceValue"))
{
string value = m_event.ParsedJson.GetValue("value").ToString();
return int.Parse(value);
}
}
return -1;
}
catch (System.Exception ex)
{
Debug.LogError(ex.StackTrace);
return -1;
}
}
async Task<int> PlayDeathCard(decimal amount, byte cardCount)
{
Debug.Log("Bet Amount => " + amount);
TransactionBlock tx_block = new TransactionBlock();
ulong requestedAmountLong = (ulong)(amount * 1_000_000_000m);
List<TransactionArgument> splitArgs = tx_block.AddMoveCallTx
(
SuiMoveNormalizedStructType.FromStr("0x2::coin::split"),
new SerializableTypeTag[] { new SerializableTypeTag("0x2::sui::SUI") },
new TransactionArgument[]
{
tx_block.gas, // Insert coin object ID here
tx_block.AddPure(new U64(requestedAmountLong)) // Insert split amount here
}
);
tx_block.AddMoveCallTx
(
SuiMoveNormalizedStructType.FromStr($"{_deathCardPackageId}{_deathCardModuleFunc}"),
new SerializableTypeTag[] { },
new TransactionArgument[]
{
tx_block.AddObjectInput(_randomPackageId),
tx_block.AddObjectInput(_deathCardChestId),
splitArgs[0],
tx_block.AddPure(new U8(cardCount))
}
);
TransactionBlockResponseOptions transactionBlockResponseOptions = new TransactionBlockResponseOptions();
transactionBlockResponseOptions.ShowEvents = true;
transactionBlockResponseOptions.ShowBalanceChanges = true;
transactionBlockResponseOptions.ShowEffects = true;
transactionBlockResponseOptions.ShowObjectChanges = true;
RpcResult<TransactionBlockResponse> result_task = await _client.SignAndExecuteTransactionBlockAsync
(
tx_block,
_account,
transactionBlockResponseOptions
);
if (result_task.Error != null)
{
Debug.Log("PlayDeathCard Error => " + result_task.Error.Message);
return -1;
}
if (result_task.Result != null && result_task.Result.BalanceChanges != null && result_task.Result.BalanceChanges.Length > 0)
{
BigInteger changeAmountBig = result_task.Result.BalanceChanges[0].Amount;
float changeAmount = GetFloatFromBigInteger(changeAmountBig);
OnBalanceChanged?.Invoke(GetFloatFromBigInteger(result_task.Result.BalanceChanges[0].Amount));
}
try
{
foreach (var m_event in result_task.Result.Events)
{
if(m_event.Type.Contains("DiceValue"))
{
string value = m_event.ParsedJson.GetValue("value").ToString();
return int.Parse(value);
}
}
return -1;
}
catch (System.Exception ex)
{
Debug.LogError(ex.StackTrace);
return -1;
}
}
}
Additional context
No response
Metadata
Metadata
Assignees
Labels
No labels