-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
23,367 additions
and
2 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import React from 'react'; | ||
import WebView from 'react-native-webview'; | ||
import { useWebViewMessage } from 'react-native-react-bridge'; | ||
import type { Message } from 'react-native-react-bridge'; | ||
import webApp from './WebApp'; | ||
import { View, StyleSheet } from 'react-native'; | ||
import { | ||
TssLibAction, | ||
type TssLibMessageResponse, | ||
type TssLibMessageRequest, | ||
TssLibMessageType, | ||
} from './common'; | ||
import '@toruslabs/tss-client'; | ||
|
||
// let promiseOn; | ||
export let bridgeEmit: (message: Message<any>) => void; | ||
|
||
export const resolveMap = new Map<string, any>(); | ||
export const rejectMap = new Map<string, any>(); | ||
|
||
// resolve promise on response | ||
const handleTssLibResponse = (data: TssLibMessageResponse) => { | ||
const { ruid, action, result } = data; | ||
// console.log('tssLib Result', ruid, action, result); | ||
const key = ruid + action; | ||
if (resolveMap.has(key)) { | ||
resolveMap.get(key)(result); | ||
resolveMap.delete(key); | ||
} else { | ||
console.log('tssLib', 'no resolver', key); | ||
} | ||
}; | ||
|
||
// handle request from webview (js_send_msg, js_read_msg) | ||
const handleTssLibRequest = async (data: TssLibMessageRequest) => { | ||
const { ruid, action, payload } = data; | ||
|
||
// console.log('tssLib Request from webview', ruid, action, payload); | ||
if (action === TssLibAction.JsReadMsg) { | ||
const { session, self_index, party, msg_type } = payload; | ||
const result = await (global as any).js_read_msg( | ||
session, | ||
self_index, | ||
party, | ||
msg_type | ||
); | ||
bridgeEmit({ | ||
type: TssLibMessageType.TssLibResponse, | ||
data: { | ||
ruid, | ||
action, | ||
result, | ||
}, | ||
}); | ||
// need to add promise to resolveMap? | ||
// console.log('done', action, result); | ||
} else if (action === TssLibAction.JsSendMsg) { | ||
const { session, self_index, party, msg_type, msg_data } = payload; | ||
const result = await (global as any).js_send_msg( | ||
session, | ||
self_index, | ||
party, | ||
msg_type, | ||
msg_data | ||
); | ||
bridgeEmit({ | ||
type: TssLibMessageType.TssLibResponse, | ||
data: { | ||
ruid, | ||
action, | ||
result, | ||
}, | ||
}); | ||
// need to add promise to resolveMap? | ||
// console.log('done', action, result); | ||
} | ||
}; | ||
|
||
export const Bridge = () => { | ||
// useWebViewMessage hook create props for WebView and handle communication | ||
// The argument is callback to receive message from React | ||
const { ref, onMessage, emit } = useWebViewMessage(async (message) => { | ||
if (message.type === 'debug') { | ||
console.log('debug', message.data); | ||
} | ||
|
||
// response handler | ||
if (message.type === TssLibMessageType.TssLibResponse) { | ||
handleTssLibResponse(message.data as TssLibMessageResponse); | ||
} | ||
if (message.type === TssLibMessageType.TssLibRequest) { | ||
await handleTssLibRequest(message.data as TssLibMessageRequest); | ||
} | ||
if (message.type === 'error') { | ||
console.log('error', message.data); | ||
// rejectMap.get(message.data.ruid + message.data.action)( | ||
} | ||
}); | ||
bridgeEmit = emit; | ||
|
||
return ( | ||
<View style={styles.container}> | ||
<WebView | ||
// ref, source and onMessage must be passed to react-native-webview | ||
ref={ref} | ||
// Pass the source code of React app | ||
source={{ html: webApp }} | ||
onMessage={onMessage} | ||
onError={console.log} | ||
/> | ||
</View> | ||
); | ||
}; | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
height: 0, | ||
display: 'none', | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
import React, { useEffect } from 'react'; | ||
import { | ||
webViewRender, | ||
emit, | ||
useNativeMessage, | ||
} from 'react-native-react-bridge/lib/web'; | ||
import * as TssLib from '@toruslabs/tss-lib'; | ||
import { | ||
TssLibAction, | ||
type TssLibMessageResponse, | ||
type TssLibMessageRequest, | ||
TssLibMessageType, | ||
} from '../common'; | ||
|
||
const style = { | ||
width: '100vw', | ||
height: '0vh', | ||
margin: 'auto', | ||
backgroundColor: 'lightblue', | ||
}; | ||
|
||
let bridgeEmit: any; | ||
const debug = (data: any) => { | ||
bridgeEmit({ | ||
type: 'debug', | ||
data, | ||
}); | ||
}; | ||
const error = (data: any) => { | ||
bridgeEmit({ | ||
type: 'error', | ||
data, | ||
}); | ||
}; | ||
|
||
let resolverMap = new Map(); | ||
|
||
if ((globalThis as any).js_read_msg === undefined) { | ||
(globalThis as any).js_read_msg = async function ( | ||
session: string, | ||
self_index: number, | ||
party: number, | ||
msg_type: string | ||
) { | ||
const ruid = session + party + msg_type; | ||
// debug({type: 'js_read_msg', msg: 'start', ruid}); | ||
bridgeEmit({ | ||
type: TssLibMessageType.TssLibRequest, | ||
data: { | ||
ruid, | ||
action: TssLibAction.JsReadMsg, | ||
payload: { session, self_index, party, msg_type }, | ||
}, | ||
}); | ||
const result = await new Promise((resolve) => { | ||
resolverMap.set(ruid + '-js_read_msg', resolve); | ||
// setTimeout(() => { | ||
// reject('timeout'); | ||
// }, 5000); | ||
}); | ||
console.log('js_read_msg DONE', result); | ||
|
||
return result; | ||
}; | ||
} | ||
|
||
if ((globalThis as any).js_send_msg === undefined) { | ||
(globalThis as any).js_send_msg = async function ( | ||
session: string, | ||
self_index: number, | ||
party: number, | ||
msg_type: string, | ||
msg_data?: string | ||
) { | ||
const ruid = session + party + msg_type; | ||
// debug({type: 'js_send_msg', msg: 'start', ruid}); | ||
bridgeEmit({ | ||
type: TssLibMessageType.TssLibRequest, | ||
data: { | ||
ruid, | ||
action: TssLibAction.JsSendMsg, | ||
payload: { session, self_index, party, msg_type, msg_data }, | ||
}, | ||
}); | ||
const result = await new Promise((resolve) => { | ||
resolverMap.set(ruid + '-js_send_msg', resolve); | ||
}); | ||
return result; | ||
}; | ||
} | ||
|
||
TssLib.default('https://node-1.node.web3auth.io/tss/v1/clientWasm'); | ||
|
||
async function handleTssLib( | ||
data: TssLibMessageRequest | ||
): Promise<TssLibMessageResponse> { | ||
const { action, payload, ruid } = data as TssLibMessageRequest; | ||
if (action === TssLibAction.BatchSize) { | ||
return { ruid, action, result: TssLib.batch_size() }; | ||
} | ||
if (action === TssLibAction.RandomGenerator) { | ||
const { state } = payload; | ||
const result = TssLib.random_generator(state); | ||
return { ruid, action, result }; | ||
} | ||
if (action === TssLibAction.RandomGeneratorFree) { | ||
const { rng } = payload; | ||
TssLib.random_generator_free(rng); | ||
return { ruid, action, result: 'done' }; | ||
} | ||
if (action === TssLibAction.ThresholdSigner) { | ||
const { session, player_index, player_count, threshold, share, pubkey } = | ||
payload; | ||
try { | ||
const result = TssLib.threshold_signer( | ||
session, | ||
player_index, | ||
player_count, | ||
threshold, | ||
share, | ||
pubkey | ||
); | ||
return { ruid, action, result }; | ||
} catch (e) { | ||
return { ruid, action, error: e }; | ||
} | ||
} | ||
if (action === TssLibAction.ThresholdSignerFree) { | ||
const { signer } = payload; | ||
TssLib.threshold_signer_free(signer); | ||
return { ruid, action, result: 'done' }; | ||
} | ||
if (action === TssLibAction.Setup) { | ||
const { signer, rng } = payload; | ||
//result from setup not able to stringify | ||
await TssLib.setup(signer, rng); | ||
return { ruid, action, result: 'done' }; | ||
} | ||
if (action === TssLibAction.Precompute) { | ||
const { parties, signer, rng } = payload; | ||
// conversion to Uint8Array needed as bridge transfer messed up Uint8Array | ||
const result = await TssLib.precompute( | ||
Uint8Array.from(parties), | ||
signer, | ||
rng | ||
); | ||
return { ruid, action, result }; | ||
} | ||
if (action === TssLibAction.LocalSign) { | ||
const { msg, hash_only, precompute } = payload; | ||
const result = TssLib.local_sign(msg, hash_only, precompute); | ||
return { ruid, action, result }; | ||
} | ||
if (action === TssLibAction.GetRFromPrecompute) { | ||
const { precompute } = payload; | ||
const result = TssLib.get_r_from_precompute(precompute); | ||
return { ruid, action, result }; | ||
} | ||
if (action === TssLibAction.LocalVerify) { | ||
const { msg, hash_only, r, sig_frags, pubkey } = payload; | ||
const result = TssLib.local_verify(msg, hash_only, r, sig_frags, pubkey); | ||
return { ruid, action, result }; | ||
} | ||
if (action === TssLibAction.Sign) { | ||
const { counterparties, msg, hash_only, signer, rng } = payload; | ||
const result = await TssLib.sign( | ||
counterparties, | ||
msg, | ||
hash_only, | ||
signer, | ||
rng | ||
); | ||
return { ruid, action, result }; | ||
} | ||
|
||
return { ruid, action, result: 'unknown action' }; | ||
} | ||
|
||
async function handleTssLibResponse( | ||
data: TssLibMessageResponse | ||
): Promise<TssLibMessageResponse> { | ||
const { action, result, ruid } = data; | ||
if (action === TssLibAction.JsSendMsg) { | ||
resolverMap.get(ruid + '-js_send_msg')(result); | ||
resolverMap.delete(ruid + '-js_send_msg'); | ||
console.log('js_send_msg resolved', result); | ||
return { ruid, action, result: 'done' }; | ||
} | ||
if (action === TssLibAction.JsReadMsg) { | ||
resolverMap.get(ruid + '-js_read_msg')(result); | ||
resolverMap.delete(ruid + '-js_read_msg'); | ||
return { ruid, action, result: 'done' }; | ||
} | ||
throw { ruid, action, result: 'done' }; | ||
} | ||
|
||
const Root = () => { | ||
useNativeMessage(async (message: { type: string; data: any }) => { | ||
if (message.type === TssLibMessageType.TssLibRequest) { | ||
try { | ||
let result = await handleTssLib(message.data); | ||
emit({ type: TssLibMessageType.TssLibResponse, data: result }); | ||
} catch (e) { | ||
error({ | ||
msg: `${message.type} error`, | ||
payload: message.data, | ||
error: e, | ||
}); | ||
} | ||
} | ||
if (message.type === TssLibMessageType.TssLibResponse) { | ||
try { | ||
await handleTssLibResponse(message.data); | ||
} catch (e) { | ||
debug({ type: 'handleTssLibResponse error', e }); | ||
error({ | ||
msg: `${message.type} error`, | ||
payload: message.data, | ||
error: e, | ||
}); | ||
} | ||
} | ||
}); | ||
|
||
bridgeEmit = emit; | ||
|
||
useEffect(() => { | ||
emit({ type: 'tsslibInit', data: 'initializing' }); | ||
}, []); | ||
|
||
return <div style={style} />; | ||
}; | ||
|
||
export default webViewRender(<Root />); |
Oops, something went wrong.