#include "JcWallet.h" #include "WalletEvent.h" #include #include #include "stdarg.h" #include #include "cocos/scripting/js-bindings/jswrapper/SeApi.h" #include "cocos/scripting/js-bindings/manual/jsb_global.h" #include "scripting/js-bindings/event/EventDispatcher.h" #include "scripting/js-bindings/manual/jsb_conversions.hpp" #include "platform/CCApplication.h" #include "base/CCScheduler.h" #include "scrypt/native-crypto.h" #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC) #include "AppDelegate.h" #import "UIViewController+Wallet.h" #import "UIViewController+QR.h" #import "UIViewController+Purchase.h" #import "GlobalData.h" #endif #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) cocos2d::Application *cocos_android_app_init(int width, int height); #endif using namespace cocos2d; NS_CC_BEGIN cocos2d::Application *g_app = nullptr; JcWallet *JcWallet::_instance = nullptr; uv_loop_t *loop = nullptr; bool _isStarted = false; uv_async_t gasync = {0}; struct AsyncTaskData { std::mutex mtx; std::list > tasks; }; // run in server thread loop void flush_tasks_in_server_loop_cb(uv_async_t *asyn) { AsyncTaskData *data = (AsyncTaskData *) asyn->data; std::lock_guard guard(data->mtx); while (!data->tasks.empty()) { // fetch task, run task data->tasks.front()(); // drop task data->tasks.pop_front(); } } void init_libuv_async_handle(uv_async_t *async) { memset(async, 0, sizeof(uv_async_t)); // uv_loop_t *loop = uv_default_loop(); loop = (uv_loop_t*)malloc(sizeof(uv_loop_t)); uv_loop_init(loop); uv_async_init(loop, async, cocos2d::flush_tasks_in_server_loop_cb); async->data = new AsyncTaskData(); uv_run(loop, UV_RUN_DEFAULT); } // run in game thread, dispatch runnable object into server loop int schedule_task_into_server_thread_task_queue(uv_async_t *asyn, std::function func) { AsyncTaskData *data = (AsyncTaskData *) asyn->data; { std::lock_guard guard(data->mtx); data->tasks.emplace_back(func); } //notify server thread to invoke `flush_tasks_in_server_loop_cb()` return uv_async_send(asyn); } #define RUN_IN_GAMETHREAD(task) \ do { \ JcWallet::getInstance()->performFunctionInCocosThread([=]() { \ task; \ });\ } while(0) #define RUN_IN_SERVERTHREAD(task) do { \ schedule_task_into_server_thread_task_queue(&gasync, [=](){ \ task; \ }); \ } while(0) bool runGlobalMethod(const char *name, se::ValueArray args, se::Value *value) { se::AutoHandleScope scope; bool ok = false; auto global = se::ScriptEngine::getInstance()->getGlobalObject(); se::Value func; if (global->getProperty(name, &func) && func.isObject()) { ok = func.toObject()->call(args, global, value); } return ok; } bool addToArgArray(se::ValueArray *args, const char *valChar) { std::string strVal(valChar); se::Value tmpVal; bool ok = true; ok &= std_string_to_seval(strVal, &tmpVal); args->push_back(tmpVal); return ok; } JcWallet::JcWallet() { JcWallet::_instance = this; _functionsToPerform.reserve(30); std::unique_lock lock(_performMutex); } void JcWallet::initEnv() { if (!_isStarted) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC) g_app = new AppDelegate(1, 1); #elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) g_app = cocos_android_app_init(1, 1); #endif EventDispatcher::init(); g_app->start(); _isStarted = true; WalletEvent::Emit("wallet_init_event", "{}"); // RUN_IN_GAMETHREAD(JcWallet::getInstance()->jsToUnity("wallet_init_event", "{}")); cocos2d::init_libuv_async_handle(&gasync); } } void JcWallet::initJSThread(std::shared_ptr wallet) { wallet->initEnv(); } void JcWallet::tick(float dt) { g_app->getScheduler()->update(dt); EventDispatcher::dispatchTickEvent(0); } JcWallet::~JcWallet() { EventDispatcher::destroy(); se::ScriptEngine::destroyInstance(); uv_loop_close(loop); JcWallet::_instance = nullptr; } char *JcWallet::runJsMethod(std::shared_ptr data) { cocos2d::log("thread: %p call method %s params: %lu", uv_thread_self(), data->methodName.c_str(), data->args.size()); se::Value value; bool ok = cocos2d::runGlobalMethod(data->methodName.c_str(), data->args, &value); static std::string result; if (value.isString()) { if (ok && !value.isNullOrUndefined()) { result = value.toString(); } else { result = ""; } cocos2d::log("method: %s ::result: %s", data->methodName.c_str(), result.c_str()); RUN_IN_GAMETHREAD(JcWallet::getInstance()->jsToUnity(data->funId, result)); // WalletEvent::Emit(data->funId.c_str(), result.c_str()); } return const_cast(result.c_str()); } void JcWallet::performFunctionInCocosThread( const std::function &function) { _performMutex.lock(); _functionsToPerform.push_back(function); _performMutex.unlock(); } void JcWallet::tickRun() { _performMutex.lock(); if( !_functionsToPerform.empty() ) { // fixed #4123: Save the callback functions, they must be invoked after '_performMutex.unlock()', otherwise if new functions are added in callback, it will cause thread deadlock. auto temp = _functionsToPerform; for( const auto &function : temp ) { function(); } _functionsToPerform.clear(); } _performMutex.unlock(); } void JcWallet::jsToUnity(std::string funId, std::string msg) { WalletEvent::Emit(funId.c_str(), msg.c_str()); } extern "C" { void initEnv() { if (!_isStarted) { new JcWallet(); std::shared_ptr wallet(JcWallet::getInstance()); std::thread([=]() { JcWallet::initJSThread(wallet); }).detach(); } } void tick(float dt) { if (_isStarted) { schedule_task_into_server_thread_task_queue(&gasync, [=](){ JcWallet::getInstance()->tick(dt); }); JcWallet::getInstance()->tickRun(); } } int runWalletMethod(const char *funId, const char *methodName, int paramCount, char **paramList) { if (!_isStarted) { return 0; } JSMethodParam *data = new JSMethodParam(); std::string methodNameStr(methodName); data->methodName = methodNameStr; data->funId = funId; data->paramCount = paramCount; addToArgArray(&data->args, funId); for (int i = 0; i < paramCount; i++) { char *arg = *(paramList + i); addToArgArray(&data->args, arg); } std::shared_ptr params(data); int result = schedule_task_into_server_thread_task_queue(&gasync, [=](){ JcWallet::getInstance()->runJsMethod(params); }); return result == 0 ? 1 : 0; } } int nativeCallJS(std::string funId, std::string methodName, std::vector sparams) { if (!_isStarted) { return 0; } JSMethodParam *data = new JSMethodParam(); data->methodName = methodName; data->funId = funId; data->paramCount = sparams.size(); addToArgArray(&data->args, funId.c_str()); for (int i = 0; i < sparams.size(); i++) { addToArgArray(&data->args, sparams[i].c_str()); } std::shared_ptr params(data); int result = schedule_task_into_server_thread_task_queue(&gasync, [=](){ JcWallet::getInstance()->runJsMethod(params); }); return result == 0 ? 1 : 0; } NS_CC_END static bool getOrCreatePlainObject_r(const char* name, se::Object* parent, se::Object** outObj) { assert(parent != nullptr); assert(outObj != nullptr); se::Value tmp; if (parent->getProperty(name, &tmp) && tmp.isObject()) { *outObj = tmp.toObject(); (*outObj)->incRef(); } else { *outObj = se::Object::createPlainObject(); parent->setProperty(name, se::Value(*outObj)); } return true; } bool jsb_wallet_callback(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); if (argc >= 2) { bool ok; std::string funId; ok = seval_to_std_string(args[0], &funId); SE_PRECONDITION2(ok, false, "Error processing arguments"); std::string msg; ok = seval_to_std_string(args[1], &msg); SE_PRECONDITION2(ok, false, "Error processing arguments"); // if funId begin with "webpage_" then call webview callback if (funId.find("webpage_") == 0) { NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init]; userInfo[@"funid"] = [NSString stringWithCString:funId.c_str() encoding:NSUTF8StringEncoding]; userInfo[@"data"] = [NSString stringWithCString:msg.c_str() encoding:NSUTF8StringEncoding]; [[NSNotificationCenter defaultCenter] postNotificationName:@"ProxyCBNotification" object: nil userInfo:userInfo]; } else { RUN_IN_GAMETHREAD(JcWallet::getInstance()->jsToUnity(funId, msg)); } return true; } return false; } SE_BIND_FUNC(jsb_wallet_callback) bool jsb_scanQRCode(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); if (argc >= 2) { bool ok; std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "Error processing arguments"); std::string title; ok = seval_to_std_string(args[1], &title); SE_PRECONDITION2(ok, false, "Error processing arguments"); NSString *ntitle = [NSString stringWithCString:title.c_str() encoding:NSUTF8StringEncoding]; NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding:NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController scanQRCode:nfunid title:ntitle]; // [window.rootViewController loadRestoreKey:nfunid oid: ntitle]; }); return true; } return false; } SE_BIND_FUNC(jsb_scanQRCode) bool jsb_signWithGoogle(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); if (argc >= 1) { bool ok; std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "Error processing arguments"); NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding:NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController signWithGoogle:nfunid]; }); return true; } return false; } SE_BIND_FUNC(jsb_signWithGoogle) bool jsb_signWithApple(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); if (argc >= 1) { bool ok; std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "Error processing arguments"); NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding:NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController signWithApple:nfunid]; }); return true; } return false; } SE_BIND_FUNC(jsb_signWithApple) bool jsb_signWithTikTok(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); if (argc >= 1) { bool ok; std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "Error processing arguments"); NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding:NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController signWithTikTok:nfunid]; }); return true; } return false; } SE_BIND_FUNC(jsb_signWithTikTok) bool jsb_signWithFacebook(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); if (argc >= 1) { bool ok; std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "Error processing arguments"); NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding:NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController signWithFacebook:nfunid]; }); return true; } return false; } SE_BIND_FUNC(jsb_signWithFacebook) bool jsb_signWithTwitter(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); if (argc >= 1) { bool ok; std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "Error processing arguments"); NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding:NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController signWithTwitter:nfunid]; }); return true; } return false; } SE_BIND_FUNC(jsb_signWithTwitter) bool jsb_signWithOAuth(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); if (argc >= 2) { bool ok; std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "Error processing arguments"); std::string jsondata; ok = seval_to_std_string(args[1], &jsondata); SE_PRECONDITION2(ok, false, "jsondata is invalid!"); NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding:NSUTF8StringEncoding]; NSString *njsondata = [NSString stringWithCString:jsondata.c_str() encoding:NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController signWithOAuth:nfunid jsondata:njsondata ]; }); return true; } return false; } SE_BIND_FUNC(jsb_signWithOAuth) bool jsb_signOutGoogle(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); if (argc >= 1) { bool ok; std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "Error processing arguments"); NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding:NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController signOutGoogle:nfunid]; }); return true; } return false; } SE_BIND_FUNC(jsb_signOutGoogle) bool JSB_showQRCode(se::State& s){ const auto& args = s.args(); size_t argc = args.size(); CC_UNUSED bool ok = true; if (argc >= 2) { std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "funid is invalid!"); std::string text; ok = seval_to_std_string(args[1], &text); SE_PRECONDITION2(ok, false, "content is invalid!"); NSString *ncontent = [NSString stringWithCString:text.c_str() encoding:NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController showQRCode:ncontent]; }); return true; } SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 4); return false; } SE_BIND_FUNC(JSB_showQRCode) bool jsb_showWebPage(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); if (argc >= 2) { bool ok; std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "Error processing arguments"); std::string url; ok = seval_to_std_string(args[1], &url); SE_PRECONDITION2(ok, false, "Error processing arguments"); NSString *nurl = [NSString stringWithCString:url.c_str() encoding:NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController showPage:nurl]; }); return true; } return false; } SE_BIND_FUNC(jsb_showWebPage) static bool JSB_queryProducts(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); CC_UNUSED bool ok = true; if (argc > 1) { std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "funid is invalid!"); std::string param0; ok = seval_to_std_string(args[1], ¶m0); SE_PRECONDITION2(ok, false, "param0 is invalid!"); NSString *nParams = [NSString stringWithCString:param0.c_str() encoding: NSUTF8StringEncoding]; NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding: NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController queryProducts:nfunid products: nParams]; }); return true; } SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2); return false; } SE_BIND_FUNC(JSB_queryProducts) static bool JSB_queryPurchase(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); CC_UNUSED bool ok = true; if (argc > 0) { std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "funid is invalid!"); NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding: NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController queryPurchase:nfunid ]; }); return true; } SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1); return false; } SE_BIND_FUNC(JSB_queryPurchase) static bool JSB_finishTransaction(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); CC_UNUSED bool ok = true; if (argc > 1) { std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "funid is invalid!"); std::string transactionid; ok = seval_to_std_string(args[1], &transactionid); SE_PRECONDITION2(ok, false, "transactionid is invalid!"); NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding: NSUTF8StringEncoding]; NSString *ntransactionid = [NSString stringWithCString:transactionid.c_str() encoding: NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController finishTransaction:nfunid transactionId:ntransactionid ]; }); return true; } SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2); return false; } SE_BIND_FUNC(JSB_finishTransaction) static bool JSB_beginBuy(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); CC_UNUSED bool ok = true; if (argc > 2) { std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "funid is invalid!"); std::string param0; ok = seval_to_std_string(args[1], ¶m0); SE_PRECONDITION2(ok, false, "param0 is invalid!"); std::string param1; ok = seval_to_std_string(args[2], ¶m1); SE_PRECONDITION2(ok, false, "param1 is invalid!"); NSString *nParam0 = [NSString stringWithCString:param0.c_str() encoding: NSUTF8StringEncoding]; NSString *nParam1 = [NSString stringWithCString:param1.c_str() encoding: NSUTF8StringEncoding]; NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding: NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController beginBuy:nfunid productId: nParam0 orderId:nParam1]; }); return true; } SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 3); return false; } SE_BIND_FUNC(JSB_beginBuy) static bool JSB_passStorageState(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); CC_UNUSED bool ok = true; if (argc > 1) { std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "funid is invalid!"); std::string param0; ok = seval_to_std_string(args[1], ¶m0); SE_PRECONDITION2(ok, false, "param0 is invalid!"); NSString *nParam0 = [NSString stringWithCString:param0.c_str() encoding: NSUTF8StringEncoding]; NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding: NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController passStorageState:nfunid account: nParam0 ]; }); return true; } SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2); return false; } SE_BIND_FUNC(JSB_passStorageState) static bool JSB_storagePass(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); CC_UNUSED bool ok = true; if (argc > 2) { std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "funid is invalid!"); std::string param0; ok = seval_to_std_string(args[1], ¶m0); SE_PRECONDITION2(ok, false, "param0 is invalid!"); std::string pass; ok = seval_to_std_string(args[2], &pass); SE_PRECONDITION2(ok, false, "param1 is invalid!"); NSString *nParam0 = [NSString stringWithCString:param0.c_str() encoding: NSUTF8StringEncoding]; NSString *nPass = [NSString stringWithCString:pass.c_str() encoding: NSUTF8StringEncoding]; NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding: NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController storagePass:nfunid account: nParam0 pass:nPass ]; }); return true; } SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 3); return false; } SE_BIND_FUNC(JSB_storagePass) static bool JSB_storageGameInfo(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); CC_UNUSED bool ok = true; if (argc > 1) { std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "funid is invalid!"); std::string param0; ok = seval_to_std_string(args[1], ¶m0); SE_PRECONDITION2(ok, false, "param0 is invalid!"); NSString *nParam0 = [NSString stringWithCString:param0.c_str() encoding: NSUTF8StringEncoding]; [[GlobalData shareInstance] setGameData:nParam0]; return true; } SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 3); return false; } SE_BIND_FUNC(JSB_storageGameInfo) static bool JSB_authGetStoragePass(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); CC_UNUSED bool ok = true; if (argc > 1) { std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "funid is invalid!"); std::string param0; ok = seval_to_std_string(args[1], ¶m0); SE_PRECONDITION2(ok, false, "param0 is invalid!"); NSString *nParam0 = [NSString stringWithCString:param0.c_str() encoding: NSUTF8StringEncoding]; NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding: NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController authGetStoragePass:nfunid account: nParam0 ]; }); return true; } SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2); return false; } SE_BIND_FUNC(JSB_authGetStoragePass) static bool JSB_getClientId(se::State &s) { const auto &args = s.args(); size_t argc = args.size(); CC_UNUSED bool ok = true; if (argc > 0) { std::string funid; ok = seval_to_std_string(args[0], &funid); SE_PRECONDITION2(ok, false, "Error processing funid"); NSString *nfunid = [NSString stringWithCString:funid.c_str() encoding: NSUTF8StringEncoding]; dispatch_async(dispatch_get_main_queue(), ^{ UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; [window.rootViewController clientLogin:nfunid ]; }); return true; } SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1); return false; } SE_BIND_FUNC(JSB_getClientId) bool jsb_register_walletevent_modules(se::Object* global) { getOrCreatePlainObject_r("jsb", global, &__jsbObj); __jsbObj->defineFunction("jcCallback", _SE(jsb_wallet_callback)); __jsbObj->defineFunction("scanQRCode", _SE(jsb_scanQRCode)); __jsbObj->defineFunction("signWithGoogle", _SE(jsb_signWithGoogle)); __jsbObj->defineFunction("signWithApple", _SE(jsb_signWithApple)); __jsbObj->defineFunction("signWithTikTok", _SE(jsb_signWithTikTok)); __jsbObj->defineFunction("signWithFacebook", _SE(jsb_signWithFacebook)); __jsbObj->defineFunction("signWithTwitter", _SE(jsb_signWithTwitter)); __jsbObj->defineFunction("signWithOAuth", _SE(jsb_signWithOAuth)); __jsbObj->defineFunction("signOutGoogle", _SE(jsb_signOutGoogle)); __jsbObj->defineFunction("showQRCode", _SE(JSB_showQRCode)); __jsbObj->defineFunction("showWebPage", _SE(jsb_showWebPage)); __jsbObj->defineFunction("queryProducts", _SE(JSB_queryProducts)); __jsbObj->defineFunction("queryPurchase", _SE(JSB_queryPurchase)); __jsbObj->defineFunction("finishTransaction", _SE(JSB_finishTransaction)); __jsbObj->defineFunction("beginBuy", _SE(JSB_beginBuy)); __jsbObj->defineFunction("authGetStoragePass", _SE(JSB_authGetStoragePass)); __jsbObj->defineFunction("storagePass", _SE(JSB_storagePass)); __jsbObj->defineFunction("getClientId", _SE(JSB_getClientId)); __jsbObj->defineFunction("passStorageState", _SE(JSB_passStorageState)); __jsbObj->defineFunction("updateGameInfo", _SE(JSB_storageGameInfo)); // JSB_signWithEmail // JSB_beginBuyJNI return true; }