import { BaseError, wrapUserFunction, createCommands } from '@jolibox/common'; import { canIUseNative, createAPI, createSyncAPI, registerCanIUse, t } from './base'; import { StandardResponse, ICoinDetailsData, IGameLeaderboardData } from '@jolibox/types'; import { context } from '@/common/context'; import { createAPIError } from '@/common/report/errors'; import { invokeNative } from '@jolibox/native-bridge'; import { IAdsContext } from '@jolibox/ads/dist/type/base'; import { adEventEmitter } from '@/common/ads'; import { taskTracker, track } from '../report'; import { JoliboxAdsForGame } from '@jolibox/ads'; import { innerFetch as fetch } from '../network'; const checkNetworkStatus = () => { const { data } = invokeNative('getNetworkStatusSync'); return !!data?.isConnected; }; const httpClient = { get: (url: string, options?: any) => fetch(url, { method: 'GET', responseType: 'json', appendHostCookie: true, ...options }).then((res) => res.response.data as T), post: (url: string, options?: any) => fetch(url, { method: 'POST', responseType: 'json', appendHostCookie: true, ...options }).then((res) => res.response.data as T) }; const adsContext: IAdsContext<'TASK'> = { httpClient, checkNetwork: checkNetworkStatus, track, eventEmitter: adEventEmitter, getWindowInfo: () => ({ width: window.innerWidth * window.devicePixelRatio, height: window.innerHeight * window.devicePixelRatio, statusBarHeight: 30 }), handleLinkClicked: (link) => { window.open(link, '_blank'); }, getContextInfo: () => { return { hostAppId: context.hostInfo?.aid ?? '1', deviceId: context.deviceInfo.did ?? '', adId: context.deviceInfo.adId ?? '', sessionId: context.sessionId ?? '', userId: context.hostUserInfo?.uid ?? '', objectType: 'TASK', objectId: context.mpId, testAdsMode: context.testAdsMode, channel: context.joliSource ?? '', deviceBrand: context.deviceInfo.brand, deviceModel: context.deviceInfo.model, osType: context.platform === 'android' ? 'ANDROID' : context.platform === 'ios' ? 'IOS' : 'PC', runtimeType: 'APP', platform: 1000, // WebSDK joliSource: context.joliSource ?? '', deviceInfo: { platform: context.platform, nativeSDKVersionCode: context.sdkInfo.nativeSDKVersionCode ?? 0 } }; } }; // const ads = new JoliboxAdsForGame(adsContext); const commands = createCommands(); const safeCallbackWrapper = wrapUserFunction(reportError as (err: Error | BaseError) => void); const getCoinDetails = createAPI('getCoinDetails', { paramsSchema: t.tuple(t.function().optional()), implement: async ( onUpdate?: (data: ICoinDetailsData) => void | Promise ): Promise> => { try { const currentType = context.mpType; // check mp type if (currentType !== 'miniApp') { reportError( createAPIError({ code: -1, msg: '[JoliboxSDK]: rewards info not supported in games. Only supported in mini apps.' }) ); return { code: 'FAILURE', message: '[JoliboxSDK]: rewards info not supported in games. Only supported in mini apps.' }; } // check native version if (!canIUseNative('requestCoinDetailsSync')) { reportError( createAPIError({ code: -1, msg: '[JoliboxSDK]: rewards info not supported in this platform.' }) ); return { code: 'FAILURE', message: '[JoliboxSDK]: rewards info not supported in this platform. lower than 1.7.1' }; } const customOnUpdate = onUpdate ? safeCallbackWrapper(onUpdate) : (() => { console.log('default update function called'); }).bind(this); const { errNo, errMsg, data } = invokeNative('requestCoinDetailsSync'); if (errNo !== 0) { throw createAPIError({ code: errNo ?? -1, msg: errMsg }); } console.log('=====> sync data', data, errNo); invokeNative('requestCoinDetailsAsync').then((res) => { if (res.errNo == 0 && res.data) { customOnUpdate(res.data); console.log('=====> res.data', res.data); } }); return { code: 'SUCCESS', message: 'Successfully retrieved coin details', data }; } catch (error) { return { code: 'FAILURE', message: '[JoliboxSDK]: Failed to get coin details: ' + (error as Error).message }; } } }); commands.registerCommand('RewardsSDK.getCoinDetails', getCoinDetails); registerCanIUse('rewards.getCoinDetails', { version: '1.3.2' }); const createRewardsAdsManager = createAPI('createRewardsAdsManager', { implement: async () => { try { const ads = new JoliboxAdsForGame(adsContext); if (context.mpType !== 'miniApp') { throw createAPIError({ code: -1, msg: '[JoliboxSDK]: createRewardsAdsManager not supported in games. Only supported in mini apps.' }); } return { code: 'SUCCESS', message: 'Successfully created RewardsAdsManager', data: { init: async () => { await ads.init(); ads.adConfig({ preloadAdBreaks: 'on', sound: 'off', onReady: () => { // do nothing } }); }, showAd: async ( callbacks: { onAdLoaded?: () => void; onAdError?: (error: Error) => void; onAdRewarded?: () => void; onAdDismissed?: () => void; }, isSpinWheel = false ) => { ads.adBreak({ type: 'reward', beforeReward: (showAdFn) => { showAdFn(); callbacks.onAdLoaded?.(); }, adDismissed: () => { // do nothing callbacks.onAdDismissed?.(); }, adViewed: () => { // do nothing }, adBreakDone: (placementInfo) => { const breakStatus = placementInfo.breakStatus; const noAdPreloaded = breakStatus === 'frequencyCapped' || breakStatus === 'other' || breakStatus === 'error' || breakStatus === 'noAdPreloaded'; if (breakStatus === 'viewed') { // reward should be given to user console.log('-----> complete watch ads'); !isSpinWheel && taskTracker.reporter({ event: 'COMPLETE_WATCH_ADS' }); callbacks.onAdRewarded?.(); } if (noAdPreloaded) { console.log('-----> no ad preloaded or error occurred', breakStatus); callbacks.onAdError?.(new Error('No ad preloaded or error occurred: ' + breakStatus)); } } }); } } }; } catch (error) { return { code: 'FAILURE', message: '[JoliboxSDK]: Failed to create RewardsAdsManager' }; } } }); commands.registerCommand('Rewards.createRewardsAdsManager', createRewardsAdsManager); registerCanIUse('rewards.createRewardsAdsManager', { version: '1.3.4' }); const getLeaderBoardData = createAPI('getLeaderBoardData', { paramsSchema: t.tuple( t.object({ gameId: t.string(), onUpdate: t.function().optional() }) ), implement: async (params: { gameId: string; onUpdate?: (data: IGameLeaderboardData) => void | Promise; }): Promise> => { try { if (!canIUseNative('requestGameLeaderboardSync')) { return { code: 'FAILURE', message: '[JoliboxSDK]: getLeaderBoardData not supported in this platform.' }; } const customOnUpdate = params.onUpdate ? safeCallbackWrapper(params.onUpdate) : (() => { console.log('default update function called'); }).bind(this); const { errNo, errMsg, data } = invokeNative('requestGameLeaderboardSync', { gameId: params.gameId }); if (errNo !== 0) { throw createAPIError({ code: errNo ?? -1, msg: errMsg }); } invokeNative('requestGameLeaderboardAsync', { gameId: params.gameId }) .then((res) => { if (res.errNo === 0 && res.data) { customOnUpdate(res.data); } else { throw createAPIError({ code: res.errNo ?? -1, msg: res.errMsg }); } }) .catch((error) => { console.error('Failed to fetch leaderboard data asynchronously: ', error); }); return { code: 'SUCCESS', message: 'Successfully retrieved leaderboard data', data }; } catch (error) { return { code: 'FAILURE', message: '[JoliboxSDK]: Failed to get leaderboard data: ' + (error as Error).message }; } } }); commands.registerCommand('RewardsSDK.getLeaderBoardData', getLeaderBoardData); registerCanIUse('rewards.getLeaderBoardData', { version: '1.3.9' });