Skip to content

Commit

Permalink
Problem: error in destroyCoreClient (fix #346) (#347)
Browse files Browse the repository at this point in the history
fix error in polling

fix crash

add _coreClient check

reformat

use weakthis

fix crash in polling

wait for async task timeout

reduce default polling time

wait at least polling time

remove automatic polling

changelog update
  • Loading branch information
leejw51crypto authored Jan 3, 2024
1 parent aaab8e7 commit a72f959
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 59 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

## [Unreleased]

## [v0.0.18-alpha] - 2023-12-19
## [v0.0.18-alpha] - 2024-1-2
- Support metamask send-tx for wallet-connect 2.0
- Support Unreal Engine 5.3.0
- Add weakptr checking for WalletConnect 2.0


## [v0.0.17-alpha] - 2023-8-10
- fix windows build
Expand Down
200 changes: 142 additions & 58 deletions Source/CronosPlayUnreal/Private/PlayCppSdkActor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ APlayCppSdkActor::APlayCppSdkActor() {
_removeClient = false;
_coreClient = NULL;
PollingEventsEnabled = false;
EnsureSessionTimeoutMilliSeconds = 60000; // in milli seconds
PollingEventsIntervalInMilliseconds = 2000; // in milli seconds
EnsureSessionTimeoutMilliSeconds = 60000; // in milli seconds
PollingEventsIntervalInMilliseconds = 100; // in milli seconds
DestroyClientWaitSeconds = 3.0f;
EnableEipTx155Tx = false;

Expand Down Expand Up @@ -289,18 +289,31 @@ void APlayCppSdkActor::OnRestoreClientFinished(bool succeed, FString message) {

void APlayCppSdkActor::EnsureSession(FEnsureSessionDelegate Out) {

AsyncTask(ENamedThreads::AnyHiPriThreadNormalTask, [this, Out]() {
TWeakObjectPtr<APlayCppSdkActor> WeakThis(this);
AsyncTask(ENamedThreads::AnyHiPriThreadNormalTask, [WeakThis, Out]() {
FWalletConnectEnsureSessionResult output;
FString result;
UE_LOG(LogTemp, Display, TEXT("EnsureSession..."));
try {
if (!WeakThis.IsValid()) {
// The object has been destroyed, handle accordingly
return;
}

WalletConnect2EnsureSessionResult sessionresult;
if (_coreClient != NULL) {
if (WeakThis->_coreClient != NULL) {
UE_LOG(LogTemp, Display, TEXT("EnsureSession blocking..."));
sessionresult = _coreClient->ensure_session_blocking(
EnsureSessionTimeoutMilliSeconds);
sessionresult = WeakThis->_coreClient->ensure_session_blocking(
WeakThis->EnsureSessionTimeoutMilliSeconds);
UE_LOG(LogTemp, Display, TEXT("EnsureSession done..."));
if (!WeakThis.IsValid()) {
// The object has been destroyed, handle accordingly
return;
}
if (WeakThis->_coreClient == NULL) {
UE_LOG(LogTemp, Display, TEXT("Blocking Canceled"));
return;
}
output.addresses.Empty();
for (int i = 0; i < sessionresult.eip155.accounts.size(); i++) {
FWalletConnectAddress newaddress;
Expand All @@ -313,7 +326,7 @@ void APlayCppSdkActor::EnsureSession(FEnsureSessionDelegate Out) {
}
assert(20 == newaddress.address.Num());
output.addresses.Add(newaddress);
_session_info.accounts.Add(
WeakThis->_session_info.accounts.Add(
UUtlis::ToHex(newaddress.address));

if (i == 0)
Expand All @@ -323,15 +336,13 @@ void APlayCppSdkActor::EnsureSession(FEnsureSessionDelegate Out) {
assert(output.addresses.Num() ==
sessionresult.addresses.size());

_session_info.sessionstate =
WeakThis->_session_info.sessionstate =
EWalletconnectSessionState::StateRestored;
_session_info.connected = true;
_session_info.chain_id = FString::FromInt(output.chain_id);

SetWalletConnectEnsureSessionResult(output);
WeakThis->_session_info.connected = true;
WeakThis->_session_info.chain_id =
FString::FromInt(output.chain_id);

// begin polling
BeginPolling(OnReceiveWalletconnectPollingDelegate);
WeakThis->SetWalletConnectEnsureSessionResult(output);

} else {
result = FString::Printf(
Expand Down Expand Up @@ -396,8 +407,6 @@ void APlayCppSdkActor::OnReceiveWalletconnectPolling(FString jsonevent,
if (result.IsEmpty()) {
UE_LOG(LogTemp, Log, TEXT("ReceiveEvent= %s"), *jsonevent);
}

BeginPolling(OnReceiveWalletconnectPollingDelegate);
}

bool APlayCppSdkActor::BeginPolling(const FWalletconnectPollingDelegate &Out) {
Expand All @@ -409,22 +418,41 @@ bool APlayCppSdkActor::BeginPolling(const FWalletconnectPollingDelegate &Out) {
if (_pollingEvents) // already polling
return false;

AsyncTask(ENamedThreads::AnyHiPriThreadNormalTask, [this, Out]() {
if (_coreClient == NULL) // if there is no client, exit
return false;

TWeakObjectPtr<APlayCppSdkActor> WeakThis(this);
AsyncTask(ENamedThreads::AnyHiPriThreadNormalTask, [WeakThis, Out]() {
if (!WeakThis.IsValid()) {
// The object has been destroyed, handle accordingly
return;
}

FWalletConnectEnsureSessionResult output;
FString userjsondata;
FString result;

_pollingEvents = true;
if (_coreClient != NULL) {
WeakThis->_pollingEvents = true;
if (WeakThis->_coreClient != NULL) {
try {
std::string jsondata =
_coreClient
WeakThis->_coreClient
->poll_events_blocking(
PollingEventsIntervalInMilliseconds)
.c_str(); // 2000 milliseconds, 2 seconds
WeakThis->PollingEventsIntervalInMilliseconds)
.c_str();

if (!WeakThis.IsValid()) {
// The object has been destroyed, handle accordingly
return;
}

if (WeakThis->_coreClient == NULL) {
UE_LOG(LogTemp, Display, TEXT("Blocking Canceled"));
return;
}
userjsondata = UTF8_TO_TCHAR(jsondata.c_str());

_pollingEvents = false;
WeakThis->_pollingEvents = false;
AsyncTask(ENamedThreads::GameThread,
[Out, userjsondata, result]() {
Out.ExecuteIfBound(userjsondata, result);
Expand All @@ -433,14 +461,18 @@ bool APlayCppSdkActor::BeginPolling(const FWalletconnectPollingDelegate &Out) {
} // end of try
catch (
const std::exception &) { // this is legimate exception, ignore
_pollingEvents = false;
AsyncTask(ENamedThreads::GameThread, [Out, userjsondata]() {
Out.ExecuteIfBound(userjsondata, TEXT("polling timeout"));
});

// in case, somehow BeginPolling is called too frequenlty
FPlatformProcess::Sleep(0.1f); // 0.1 seconds
} // end of catch
if (WeakThis.IsValid()) {
WeakThis->_pollingEvents = false;
AsyncTask(ENamedThreads::GameThread, [Out, userjsondata]() {
Out.ExecuteIfBound(userjsondata,
TEXT("polling timeout"));
});

// in case, somehow BeginPolling is called too frequenlty
FPlatformProcess::Sleep(0.1f); // 0.1 seconds
}

} // end of catch
}
});
return true;
Expand Down Expand Up @@ -475,6 +507,7 @@ void APlayCppSdkActor::GetConnectionString(FString &output, bool &success,
}
String qrcode = _coreClient->get_connection_string();
output = UTF8_TO_TCHAR(qrcode.c_str());
UE_LOG(LogTemp, Log, TEXT("GetConnectionString: %s"), *output);

success = true;
} catch (const std::exception &e) {
Expand Down Expand Up @@ -550,8 +583,10 @@ void APlayCppSdkActor::SignPersonal(FString user_message,
// if no address, return
if (address.Num() == 0)
return;

TWeakObjectPtr<APlayCppSdkActor> WeakThis(this);
AsyncTask(ENamedThreads::AnyHiPriThreadNormalTask,
[Out, coreclient, user_message, address, this]() {
[Out, coreclient, user_message, address, WeakThis]() {
FWalletSignTXEip155Result output;
try {

Expand All @@ -560,8 +595,17 @@ void APlayCppSdkActor::SignPersonal(FString user_message,
for (int i = 0; i < address.Num(); i++) {
dstaddress[i] = address[i];
}
Vec<uint8_t> sig1 = _coreClient->sign_personal_blocking(
TCHAR_TO_UTF8(*user_message), dstaddress);
Vec<uint8_t> sig1 =
WeakThis->_coreClient->sign_personal_blocking(
TCHAR_TO_UTF8(*user_message), dstaddress);
if (!WeakThis.IsValid()) {
// The object has been destroyed, handle accordingly
return;
}
if (WeakThis->_coreClient == NULL) {
UE_LOG(LogTemp, Display, TEXT("Blocking Canceled"));
return;
}

copyVecToTArray(sig1, output.signature);
assert(sig1.size() == output.Num());
Expand Down Expand Up @@ -589,9 +633,17 @@ void APlayCppSdkActor::SignEip155Transaction(
// if no address, return
if (address.Num() == 0 || chain_id == 0)
return;

TWeakObjectPtr<APlayCppSdkActor> WeakThis(this);

AsyncTask(ENamedThreads::AnyHiPriThreadNormalTask, [Out, coreclient,
address, chain_id, info,
this]() {
WeakThis]() {
if (!WeakThis.IsValid()) {
// The object has been destroyed, handle accordingly
return;
}

FWalletSignTXEip155Result output;

try {
Expand All @@ -611,13 +663,23 @@ void APlayCppSdkActor::SignEip155Transaction(
myinfo.common.nonce = TCHAR_TO_UTF8(*info.nonce);
// todo: chainid is included, wc 2.0 not work
myinfo.common.chainid =
EnableEipTx155Tx ? myinfo.common.chainid : 0;
WeakThis->EnableEipTx155Tx ? myinfo.common.chainid : 0;

if (_coreClient != NULL) {
if (WeakThis->_coreClient != NULL) {

Vec<uint8_t> sig1 =
_coreClient->sign_eip155_transaction_blocking(myinfo,
dstaddress);
WeakThis->_coreClient->sign_eip155_transaction_blocking(
myinfo, dstaddress);

if (!WeakThis.IsValid()) {
// The object has been destroyed, handle accordingly
return;
}

if (WeakThis->_coreClient == NULL) {
UE_LOG(LogTemp, Display, TEXT("Blocking Canceled"));
return;
}

copyVecToTArray(sig1, output.signature);
assert(sig1.size() == output.Num());
Expand Down Expand Up @@ -649,9 +711,16 @@ void APlayCppSdkActor::SendEip155Transaction(
// if no address, return
if (address.Num() == 0 || chain_id == 0)
return;

TWeakObjectPtr<APlayCppSdkActor> WeakThis(this);
AsyncTask(ENamedThreads::AnyHiPriThreadNormalTask, [Out, coreclient,
address, chain_id, info,
this]() {
WeakThis]() {
if (!WeakThis.IsValid()) {
// The object has been destroyed, handle accordingly
return;
}

FWalletSendTXEip155Result output;

try {
Expand All @@ -672,12 +741,21 @@ void APlayCppSdkActor::SendEip155Transaction(
myinfo.common.nonce = TCHAR_TO_UTF8(*info.nonce);
// todo: chainid is included, wc 2.0 not work
myinfo.common.chainid =
EnableEipTx155Tx ? myinfo.common.chainid : 0;
if (_coreClient != NULL) {
WeakThis->EnableEipTx155Tx ? myinfo.common.chainid : 0;
if (WeakThis->_coreClient != NULL) {

Vec<uint8_t> tx_hash =
_coreClient->send_eip155_transaction_blocking(myinfo,
dstaddress);
WeakThis->_coreClient->send_eip155_transaction_blocking(
myinfo, dstaddress);
if (!WeakThis.IsValid()) {
// The object has been destroyed, handle accordingly
return;
}

if (WeakThis->_coreClient == NULL) {
UE_LOG(LogTemp, Display, TEXT("Blocking Canceled"));
return;
}

copyVecToTArray(tx_hash, output.tx_hash);
assert(tx_hash.size() == output.Num());
Expand All @@ -699,23 +777,29 @@ void APlayCppSdkActor::SendEip155Transaction(

void APlayCppSdkActor::destroyCoreClient() {
_removeClient = true;
UE_LOG(LogTemp, Log, TEXT("PlayCppSdkActor destroyCoreClient Start"));

if (_coreClient != NULL) {
UE_LOG(LogTemp, Log, TEXT("PlayCppSdkActor destroyCoreClient"));

AsyncTask(ENamedThreads::AnyHiPriThreadNormalTask, [this]() {
// wait for DesroyClientWaitSeconds
FPlatformProcess::Sleep(DestroyClientWaitSeconds);
float waittime = (float)PollingEventsIntervalInMilliseconds / 1000.0f +
DestroyClientWaitSeconds + 1.0f;
UE_LOG(LogTemp, Log,
TEXT("PlayCppSdkActor destroyCoreClient waittime: %f"),
waittime);
::com::crypto::game_sdk::Walletconnect2Client *coreclient = _coreClient;
_coreClient = NULL;

if (_coreClient != NULL) {
UE_LOG(LogTemp, Log, TEXT("PlayCppSdkActor destroyCoreClient"));
FPlatformProcess::Sleep(waittime); // give time to finish asynctask

// restored back, close tokio-runtime
// ue4 editor gracefully closed
// TODO crashed here? Likely to be fixed, but need to be careful
Box<Walletconnect2Client> tmpwallet =
Box<Walletconnect2Client>::from_raw(_coreClient);
_coreClient = NULL;
_removeClient = false;
}
});
// restored back, close tokio-runtime
// ue4 editor gracefully closed
// TODO crashed here? Likely to be fixed, but need to be careful
Box<Walletconnect2Client> tmpwallet =
Box<Walletconnect2Client>::from_raw(coreclient);

_removeClient = false;
}
}

void StopWalletConnect() {}
Expand Down

0 comments on commit a72f959

Please sign in to comment.