Skip to content

Commit

Permalink
refactor: Add SSE to make signing asynchronous with prompt
Browse files Browse the repository at this point in the history
  • Loading branch information
humblenginr committed Aug 31, 2024
1 parent 2a31fad commit 63289a8
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 26 deletions.
12 changes: 1 addition & 11 deletions client/usif/webui/sendtx.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,6 @@ func sign_transaction(wrs *rmtsrv.WebsocketServer)func (w http.ResponseWriter, r

// Non-multisig transaction ...
st.Tx2Sign = string(tx.Serialize())
fmt.Println("Sending signtx msg over ws")

msg := rmtcmn.Msg{Type: rmtcmn.SignTransaction, Payload: st}

Expand All @@ -233,16 +232,7 @@ func sign_transaction(wrs *rmtsrv.WebsocketServer)func (w http.ResponseWriter, r
err = error.Error()
goto error
}
fmt.Println("waiting for ws response...")
msg = <-wrs.Signtxchan
fmt.Println("received ws response...")
if(msg.Type == rmtcmn.InternalError){
w.Write([]byte(""))
return
}
rawhex := msg.Payload.(string)
w.Write([]byte(rawhex))

return
} else {
err = "Bad request"
goto error
Expand Down
70 changes: 70 additions & 0 deletions client/usif/webui/webui.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,75 @@ func get_remote_wallet_status(wrs rmtcmn.WalletRemoteServer)func (w http.Respons
}
}

func SSEHandler(wrs *rmtserver.WebsocketServer) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")

flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
return
}

ticker := time.NewTicker(10 * time.Second) // Keep-alive every 10 seconds
defer ticker.Stop()

for {
select {
case ev := <-wrs.Signtxchan:
fmt.Println("received sign transaction")
if ev.Type == rmtcmn.InternalError {
fmt.Println("Could not sign a transaction: ", ev.Payload.(string))
continue
}
rawhex, ok := ev.Payload.(string)
if !ok {
fmt.Println("no rawhex")
continue
}
fmt.Println("sending the data")
fmt.Fprintf(w, "data: %s\n\n", rawhex)
flusher.Flush()
case <-ticker.C:
// Send a keep-alive comment to prevent connection timeout
fmt.Fprintf(w, ": keep-alive\n\n")
flusher.Flush()
}
}
}
}


func stream_signed_tx_resp(wrs *rmtserver.WebsocketServer)func (w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
// set up headers and stuff
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")

// Flush the headers immediately
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
return
}

// wait for a signtx message and send it to the client
for {
ev := <-wrs.Signtxchan
if(ev.Type == rmtcmn.InternalError){
fmt.Println("Could not sign a transaction: ", ev.Payload.(string))
continue
}
fmt.Fprintf(w, "data: %s\n\n", ev.Payload.(string))
flusher.Flush()
}
}
}


func ServerThread() {
wrs := rmtserver.NewWebsocketServer(&rmtserver.MsgHandler{})

Expand All @@ -205,6 +274,7 @@ func ServerThread() {
http.HandleFunc("/snd", p_snd)
http.HandleFunc("/balance.json", json_balance)
http.HandleFunc("/payment.zip", dl_payment)
http.HandleFunc("/signed_tx_stream", SSEHandler(&wrs))
http.HandleFunc("/sign_transaction", sign_transaction(&wrs))
http.HandleFunc("/rmtwallet_status", get_remote_wallet_status(&wrs))
http.HandleFunc("/balance.zip", dl_balance)
Expand Down
25 changes: 19 additions & 6 deletions client/www/templates/send.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,23 @@
f();
})();

function signed_tx_response_stream(){
const source = new EventSource("/signed_tx_stream")
source.onerror = (err) => {
console.log(err)
}
source.onmessage = (event) => {
console.log("OnMessage Called:")
console.log({event: event, data: event.data})
if(confirm("Received a transaction from remote wallet. Do you want to push to the mempool?")){
pushtx(event.data)
}
}
}
(function(){
signed_tx_response_stream()
})();

function build_change_list() {
var virgincounter = 0
while (changeaddrsel.options.length>1) changeaddrsel.remove(1)
Expand Down Expand Up @@ -747,14 +764,10 @@

xhr.open( 'POST', '/sign_transaction', true );
xhr.onreadystatechange = function ( response ) {
console.log(response)
if (xhr.readyState == 4) {
console.log(xhr.responseText)
if(xhr.responseText && xhr.status === 200) {
pushtx(xhr.responseText)
} else {
if(xhr.status != 200) {
alert("Error: " + xhr.responseText)
}
}
}
};
xhr.send( data );
Expand Down
Binary file modified remote-wallet/gateway/gateway
Binary file not shown.
17 changes: 9 additions & 8 deletions remote-wallet/gateway/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ func (w WSMessageWriter) Write(msg common.Msg) error {
}

func main(){
// initialize configuration
common.InitConfig()
fmt.Println("Establishing connection with ", common.FLAG.WebsocketServerAddr, "...")
wrc := WalletRemoteGateway{}
err := wrc.Open("ws://"+common.FLAG.WebsocketServerAddr)
// establish connection with gocoin node
wrg := WalletRemoteGateway{}
err := wrg.Open("ws://"+common.FLAG.WebsocketServerAddr)
if err != nil {
panic(err)
}
h := MsgHandler{WalletBinaryPath: common.FLAG.WalletFolderPath+"/wallet", WalletFolderPath: common.FLAG.WalletFolderPath}
writer := WSMessageWriter{conn: wrc.c}

// keep sending ping every 5 seconds so that the server can be aware of the connection
writer := WSMessageWriter{conn: wrg.c}
go func(){
// keep sending ping every 5 seconds so that the server can be aware of the connection
for range time.Tick(time.Second * 5) {
ping := common.Msg{Type: common.Ping, Payload: nil}
err = writer.Write(ping)
Expand All @@ -44,9 +44,10 @@ func main(){
}
}
}()

// process the requests from the gocoin node
h := MsgHandler{WalletBinaryPath: common.FLAG.WalletFolderPath+"/wallet", WalletFolderPath: common.FLAG.WalletFolderPath}
for {
msg, err := wrc.Read()
msg, err := wrg.Read()
if err != nil {
fmt.Println(err)
break
Expand Down
1 change: 0 additions & 1 deletion remote-wallet/server/websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ func (s *WebsocketServer) watchPings(){
for {
select {
case <-s.Pingchan:
fmt.Println("Received Ping")
ticker.Reset(PingWaitPeriod * time.Second)
case <-ticker.C:
// harsh attempt to clean up resources
Expand Down

0 comments on commit 63289a8

Please sign in to comment.