UNPKG

@luffalab/luffa-endless-sdk

Version:

luffa endless ts sdk

253 lines (237 loc) 8.06 kB
import { AccountInfo, EndlessLuffaSdk, MethodName } from '../index'; import type { IMessageData, EndLessSDKEventListenersType, EndLessSDKEventPayload, EndLessSDKEventType } from './types'; import { EndLessSDKEvent, IResponseMessageData } from './types'; import { getNetworkInfo, isLuffaMiniProgramWebview, isLuffaMiniProgram, isLuffa, networkMap } from '../utils'; export class PostMessage { private static _instance: PostMessage; callbacks: { [key: string]: (data: unknown) => void; } = {}; private listeners: EndLessSDKEventListenersType = {}; constructor() { if (PostMessage._instance) return PostMessage._instance; PostMessage._instance = this; if (isLuffa()) { window.endlessWallet = { sendResponse: this.sendResponse.bind(this), }; } } // wallet emit sdk // SDK processing method itself private readonly receive = (msg: { data: IResponseMessageData }) => { const eventType = msg.data.methodName as EndLessSDKEventType | MethodName; // sdk callbacks if (this.callbacks[msg.data.uuid + eventType]) { this.callbacks[msg.data.uuid + eventType](msg.data.data); delete this.callbacks[msg.data.uuid + eventType]; } // Some events are being monitored by dapp and require running a monitoring callback switch (eventType) { case EndLessSDKEvent.NETWORK_CHANGE: { let network = getNetworkInfo(msg.data.data.network); if (isLuffaMiniProgram()) { network = msg.data.data; } this.emit(eventType, network); break; } // wallet to sdk send onAccountChange | connect // sdk to dapp send event // CONNECT and ACCOUNT_CHANGE return account as AccountAddress case EndLessSDKEvent.CONNECT: case EndLessSDKEvent.ACCOUNT_CHANGE: { const accountInfo: AccountInfo = { ...msg.data.data, }; if (msg?.data?.data?.account) { EndlessLuffaSdk.setAccountAddress(msg.data.data.account); } else { EndlessLuffaSdk.setAccountAddress(null); } this.emit(eventType, accountInfo); break; } case EndLessSDKEvent.DISCONNECT: { EndlessLuffaSdk.setAccountAddress(null); this.emit(eventType, msg.data.data); break; } default: this.emit(eventType as EndLessSDKEventType, msg.data.data); break; } }; readonly addListener = <K extends EndLessSDKEventType>( methodName: K, callback: (payload: EndLessSDKEventPayload<K>) => void ) => { if (!this.listeners[methodName]) { this.listeners[methodName] = []; } this.listeners[methodName].push(callback); }; readonly removeListener = <K extends EndLessSDKEventType>( methodName: K, callback?: (payload: EndLessSDKEventPayload<K>) => void ) => { if (callback) { const index = this.listeners[methodName]?.indexOf(callback) ?? -1; if (index > -1) { this.listeners?.[methodName]?.splice(index, 1); } } else { this.listeners[methodName] = []; } }; readonly emit = <K extends EndLessSDKEventType>(methodName: K, payload: EndLessSDKEventPayload<K>) => { this.listeners?.[methodName]?.forEach((d) => d(payload)); }; readonly sendMessage = (data: IMessageData, callback?: (data: any) => void) => { try { if (isLuffa()) { this.sendLuffaMessage(data, callback); return; } if (isLuffaMiniProgram() || isLuffaMiniProgramWebview()) { this.sendMiniProgramMessage(data, callback); return; } } catch (error) { console.error('sendMessage error: ', error); } }; private sendLuffaMessage(data: IMessageData, callback?: (data: any) => void) { const initData = data?.initData || EndlessLuffaSdk.getIninData(); data.initData = { ...(initData || {}), network: networkMap[initData.network] ?? initData.network }, data.from = EndlessLuffaSdk.getAccountAddress(); if (callback) { this.callbacks[data.uuid + data.methodName] = callback; } if (window?._endlessWallet) { window._endlessWallet?.sendMessage(JSON.stringify(data)); } else if (window?.webkit && window?.webkit?.messageHandlers?._endlessWallet) { window.webkit.messageHandlers._endlessWallet?.postMessage(data); } } private sendResponse(response: string) { const responseData = JSON.parse(response); console.log('responseData: ', responseData); this.receive({ data: responseData, }); } private sendMiniProgramMessage(data: IMessageData, callback?: (data: any) => void) { let funName = 'invokeNativePlugin'; const accountAddress = EndlessLuffaSdk.getAccountAddress(); const initData = EndlessLuffaSdk.getIninData(); let api_name = 'luffaWebRequest'; let params = { api_name, data: { func: data.methodName, chainType: 'endless', ...data, initData: { ...initData, network: networkMap[initData.network] ?? initData.network }, from: accountAddress, }, }; let callbackSuccessFun = (res: any) => {}; let callbackErrorFun = (res: any) => {}; switch (data.methodName) { case MethodName.NETWORK_CHANGE: this.emit(data.methodName as unknown as EndLessSDKEventType, data.data as any); return; case MethodName.DISCONNECT: EndlessLuffaSdk.setAccountAddress(null); this.emit(data.methodName as unknown as EndLessSDKEventType, undefined); case MethodName.CONNECT: case MethodName.GETACCOUNT: callbackSuccessFun = (res) => { EndlessLuffaSdk.setAccountAddress(res.data.account); callback && callback({ account: res?.data?.address || '', ...(res.data || {}), }); }; callbackErrorFun = (res) => { callback && callback({ account: '', }); }; break; case MethodName.SIGN_MESSAGE: case MethodName.SIGN_BUILD_TRANSACTION: case MethodName.SIGN_AND_SUBMIT_TRANSACTION: callbackSuccessFun = (res: any) => { callback && callback({ status: 'success', ...(res.data || {}), }); }; callbackErrorFun = (res: any) => { callback && callback({ status: 'error', ...(res.data || {}), }); }; break; default: callbackSuccessFun = (res: any) => { callback && callback({ status: 'success', ...(res.data || {}), }); }; callbackErrorFun = (res: any) => { callback && callback({ status: 'error', ...(res.data || {}), }); }; break; } console.log('funName: ', funName); console.log('params: ', params); if (isLuffaMiniProgram()) { window.wx[funName]({ ...params, complete: (res: any) => { console.log(`wx ${funName} res: `, res); if (res.status === 'success') { callbackSuccessFun(res); this.receive({ data: res, }); } else { callbackErrorFun(res); } } }); } else if (isLuffaMiniProgramWebview()) { window.WeixinJSBridge?.invoke(funName, params, (res) => { console.log(`WeixinJSBridge ${funName} res: `, res); if (res.status === 'success') { callbackSuccessFun(res); this.receive({ data: res, }); } else { callbackErrorFun(res); } }); } } }