1
1
import { WebView } from "react-native-webview" ;
2
- import Constants from "expo-constants" ;
3
2
import {
4
3
Button ,
5
4
Modal ,
@@ -13,20 +12,50 @@ import { Network } from "../../../data/constants";
13
12
import { useRef , useState } from "react" ;
14
13
import * as Uint8ArrayUtils from "../../../utils/uint8Array" ;
15
14
import { useFacade } from "../../../data/facades" ;
15
+ import { Output } from "@/data/facades/wallet/types" ;
16
+ import SendTransactionModal from "@/components/browser/SendTransactionModal" ;
16
17
17
18
type Message = {
18
19
id : number ;
19
20
type : string ;
20
21
data : Record < string , unknown > | null ;
21
22
} ;
22
23
24
+ const BRIDGE_URLS : Record < Network , string > = {
25
+ [ Network . MAINNET ] : "https://bridge.ironfish.network/" ,
26
+ [ Network . TESTNET ] : "https://testnet.bridge.ironfish.network/" ,
27
+ } ;
28
+
29
+ export type Mint = {
30
+ value : string ;
31
+ assetId ?: string ;
32
+ name ?: string ;
33
+ metadata ?: string ;
34
+ } ;
35
+
36
+ export type Burn = {
37
+ value : string ;
38
+ assetId : string ;
39
+ } ;
40
+
41
+ type GeneralTransactionData = {
42
+ from : string ;
43
+ fee ?: string ;
44
+ outputs ?: Output [ ] ;
45
+ mints ?: Mint [ ] ;
46
+ burns ?: Burn [ ] ;
47
+ } ;
48
+
23
49
class MessageHandler {
24
50
activeAccount : { name : string ; address : string } | null = null ;
25
- activeAccountName = null ;
26
51
connectRequest : {
27
52
resolve : ( address : string | null ) => void ;
28
53
reject : ( ) => void ;
29
54
} | null = null ;
55
+ sendTransactionRequest : {
56
+ resolve : ( transaction : string ) => void ;
57
+ reject : ( ) => void ;
58
+ } | null = null ;
30
59
31
60
async updateActiveAccount (
32
61
activeAccount : { name : string ; address : string } | null ,
@@ -38,9 +67,20 @@ class MessageHandler {
38
67
}
39
68
}
40
69
70
+ async rejectSendTransactionRequest ( ) {
71
+ this . sendTransactionRequest ?. reject ( ) ;
72
+ this . sendTransactionRequest = null ;
73
+ }
74
+
75
+ async resolveSendTransactionRequest ( transaction : string ) {
76
+ this . sendTransactionRequest ?. resolve ( transaction ) ;
77
+ this . sendTransactionRequest = null ;
78
+ }
79
+
41
80
async handleMessage (
42
81
data : string ,
43
82
showAccountModal : ( ) => void ,
83
+ showSendTransactionModal : ( data : GeneralTransactionData ) => void ,
44
84
postMessage ?: ( data : string ) => void ,
45
85
) {
46
86
console . log ( data ) ;
@@ -106,6 +146,40 @@ class MessageHandler {
106
146
} ,
107
147
} ) ,
108
148
) ;
149
+ } else if ( message . type === "generalTransaction" ) {
150
+ if ( ! message . data ) {
151
+ console . error ( "No data" ) ;
152
+ return ;
153
+ }
154
+ const data = message . data as GeneralTransactionData ;
155
+ if ( data . from !== this . activeAccount ?. address ) {
156
+ console . error ( "From address does not match active account" ) ;
157
+ return ;
158
+ }
159
+ if ( data . mints && data . mints . length > 0 ) {
160
+ console . error ( "Mints are not supported" ) ;
161
+ return ;
162
+ }
163
+ if ( data . burns && data . burns . length > 0 ) {
164
+ console . error ( "Burns are not supported" ) ;
165
+ return ;
166
+ }
167
+
168
+ showSendTransactionModal ( {
169
+ ...data ,
170
+ // Replace the public address with the name of the account
171
+ from : this . activeAccount . name ,
172
+ } ) ;
173
+ const transaction = await new Promise < string > ( ( resolve , reject ) => {
174
+ this . sendTransactionRequest = { resolve, reject } ;
175
+ } ) ;
176
+ postMessage ?.(
177
+ JSON . stringify ( {
178
+ id : message . id ,
179
+ type : "generalTransaction" ,
180
+ data : { transaction } ,
181
+ } ) ,
182
+ ) ;
109
183
} else {
110
184
console . error ( `Invalid message type: ${ message . type } ` ) ;
111
185
}
@@ -117,9 +191,11 @@ export default function MenuDebugBrowser() {
117
191
const messageHandler = useRef ( new MessageHandler ( ) ) ;
118
192
const facade = useFacade ( ) ;
119
193
120
- const [ modalVisible , setModalVisible ] = useState ( false ) ;
194
+ const [ accountModalVisible , setAccountModalVisible ] = useState ( false ) ;
195
+ const [ sendTransactionData , setSendTransactionData ] =
196
+ useState < GeneralTransactionData | null > ( null ) ;
121
197
const accounts = facade . getAccounts . useQuery ( undefined , {
122
- enabled : modalVisible ,
198
+ enabled : accountModalVisible ,
123
199
} ) ;
124
200
125
201
const js = `
@@ -140,6 +216,10 @@ export default function MenuDebugBrowser() {
140
216
window.rpccalls[message.id].resolve(message.data.address);
141
217
} else if (message.type === "getBalances") {
142
218
window.rpccalls[message.id].resolve(message.data.balances);
219
+ } else if (message.type === "generalTransaction") {
220
+ window.rpccalls[message.id].resolve(message.data.transaction);
221
+ } else if (message.type === "error") {
222
+ window.rpccalls[message.id].reject(message.data.error);
143
223
}
144
224
});
145
225
@@ -187,11 +267,27 @@ export default function MenuDebugBrowser() {
187
267
console.log(result);
188
268
return result;
189
269
}
270
+ async generalTransaction(e) {
271
+ if (!this.#address) {
272
+ throw new Error("Connect first");
273
+ }
274
+ const id = window.rpccounter++;
275
+ window.ReactNativeWebView.postMessage(JSON.stringify({
276
+ id,
277
+ type: "generalTransaction",
278
+ data: e,
279
+ }));
280
+ const result = await new Promise((resolve, reject) => {
281
+ window.rpccalls[id] = { resolve, reject };
282
+ });
283
+ console.log(result);
284
+ return result;
285
+ }
190
286
}
191
287
192
288
window.ironfish = new Proxy(new IronFishBridge(), {
193
289
get: (obj, property, receiver) => {
194
- if (!property in obj) {
290
+ if (!( property in obj) ) {
195
291
const message = \`ERROR: Please implement $\{property\} in IronFishBridge\`;
196
292
console.error(message);
197
293
return;
@@ -212,16 +308,16 @@ export default function MenuDebugBrowser() {
212
308
< View style = { styles . container } >
213
309
< Modal
214
310
animationType = "slide"
215
- visible = { modalVisible }
311
+ visible = { accountModalVisible }
216
312
onRequestClose = { ( ) => {
217
- setModalVisible ( false ) ;
313
+ messageHandler . current . updateActiveAccount ( null ) ;
314
+ setAccountModalVisible ( false ) ;
218
315
} }
219
316
>
220
317
< SafeAreaView >
221
318
< View style = { { paddingTop : 40 , paddingHorizontal : 4 } } >
222
319
< Text style = { { fontSize : 20 , textAlign : "center" } } >
223
- This website would like to connect to your wallet. Choose an
224
- account to connect, or click Cancel.
320
+ This website would like to connect to your wallet.
225
321
</ Text >
226
322
< Text style = { { textAlign : "center" } } >
227
323
Choose an account to connect, or click Cancel.
@@ -234,30 +330,44 @@ export default function MenuDebugBrowser() {
234
330
name : a . name ,
235
331
address : a . publicAddress ,
236
332
} ) ;
237
- setModalVisible ( false ) ;
333
+ setAccountModalVisible ( false ) ;
238
334
} }
239
335
title = { `${ a . name } (${ a . balances . iron . confirmed } $IRON)` }
240
336
/>
241
337
) ) }
242
338
< Button
243
339
onPress = { ( ) => {
244
340
messageHandler . current . updateActiveAccount ( null ) ;
245
- setModalVisible ( false ) ;
341
+ setAccountModalVisible ( false ) ;
246
342
} }
247
343
title = "Cancel"
248
344
/>
249
345
</ View >
250
346
</ SafeAreaView >
251
347
</ Modal >
348
+ < SendTransactionModal
349
+ sendTransactionData = { sendTransactionData }
350
+ cancel = { ( ) => {
351
+ messageHandler . current . rejectSendTransactionRequest ( ) ;
352
+ setSendTransactionData ( null ) ;
353
+ } }
354
+ success = { ( hash ) => {
355
+ messageHandler . current . resolveSendTransactionRequest ( hash ) ;
356
+ setSendTransactionData ( null ) ;
357
+ } }
358
+ />
252
359
< WebView
253
- source = { { uri : "https://testnet.bridge.ironfish.network" } }
360
+ source = { { uri : BRIDGE_URLS [ Network . MAINNET ] } }
254
361
ref = { ( r ) => ( webref . current = r ) }
255
362
injectedJavaScriptBeforeContentLoaded = { js }
256
363
onMessage = { ( event ) => {
257
364
messageHandler . current . handleMessage (
258
365
event . nativeEvent . data ,
259
366
( ) => {
260
- setModalVisible ( true ) ;
367
+ setAccountModalVisible ( true ) ;
368
+ } ,
369
+ ( data ) => {
370
+ setSendTransactionData ( data ) ;
261
371
} ,
262
372
webref . current ?. postMessage ,
263
373
) ;
@@ -271,6 +381,5 @@ export default function MenuDebugBrowser() {
271
381
const styles = StyleSheet . create ( {
272
382
container : {
273
383
flex : 1 ,
274
- marginTop : Constants . statusBarHeight ,
275
384
} ,
276
385
} ) ;
0 commit comments