diff --git a/tools/walletextension/Dockerfile b/tools/walletextension/Dockerfile index ddc6223560..0e3dcd7a2e 100644 --- a/tools/walletextension/Dockerfile +++ b/tools/walletextension/Dockerfile @@ -16,6 +16,10 @@ FROM system as get-dependencies # setup container data structure RUN mkdir -p /home/obscuro/go-obscuro + +# Install Node.js and npm (needed for frontend) +RUN apk add --update nodejs npm + # Ensures container layer caching when dependencies are not changed WORKDIR /home/obscuro/go-obscuro COPY go.mod . @@ -27,7 +31,22 @@ FROM get-dependencies as build-wallet # make sure the geth network code is available COPY . /home/obscuro/go-obscuro -# build the contract deployer exec +# Create .env file for frontend +WORKDIR /home/obscuro/go-obscuro/tools/walletextension/frontend +RUN if [ "$TESTNET_TYPE" = "dev-testnet" ]; then \ + echo "NEXT_PUBLIC_API_GATEWAY_URL=https://dev-testnet.obscu.ro" > .env; \ + elif [ "$TESTNET_TYPE" = "uat-testnet" ]; then \ + echo "NEXT_PUBLIC_API_GATEWAY_URL=https://uat-testnet.obscu.ro" > .env; \ + elif [ "$TESTNET_TYPE" = "sepolia-testnet" ]; then \ + echo "NEXT_PUBLIC_API_GATEWAY_URL=https://testnet.obscu.ro" > .env; \ + else \ + echo "NEXT_PUBLIC_API_GATEWAY_URL=http://127.0.0.1:3000" > .env; \ + fi +# Run npm build for frontend +RUN npm install +RUN npm run build + +# build the gateway executable WORKDIR /home/obscuro/go-obscuro/tools/walletextension/main RUN --mount=type=cache,target=/root/.cache/go-build \ go build -o ../bin/wallet_extension_linux diff --git a/tools/walletextension/api/server.go b/tools/walletextension/api/server.go index b725975ef4..dc6b512e25 100644 --- a/tools/walletextension/api/server.go +++ b/tools/walletextension/api/server.go @@ -11,13 +11,11 @@ import ( "github.com/ten-protocol/go-ten/tools/walletextension/common" ) -//go:embed static -//go:embed staticOG +//go:embed all:static var staticFiles embed.FS const ( - staticDir = "static" - staticDirOG = "staticOG" + staticDir = "static" ) // Server is a wrapper for the http server @@ -67,13 +65,7 @@ func createHTTPServer(address string, routes []Route) *http.Server { if err != nil { panic(fmt.Sprintf("could not serve static files. Cause: %s", err)) } - serveMux.Handle(common.PathViewingKeys, http.StripPrefix(common.PathViewingKeys, http.FileServer(http.FS(noPrefixStaticFiles)))) - - noPrefixStaticFilesOG, err := fs.Sub(staticFiles, staticDirOG) - if err != nil { - panic(fmt.Errorf("could not serve static files. Cause: %w", err).Error()) - } - serveMux.Handle(common.PathObscuroGateway, http.StripPrefix(common.PathObscuroGateway, http.FileServer(http.FS(noPrefixStaticFilesOG)))) + serveMux.Handle(common.PathObscuroGateway, http.StripPrefix(common.PathObscuroGateway, http.FileServer(http.FS(noPrefixStaticFiles)))) // Creates the actual http server with a ReadHeaderTimeout to avoid Potential Slowloris Attack server := &http.Server{Addr: address, Handler: serveMux, ReadHeaderTimeout: common.ReaderHeadTimeout} diff --git a/tools/walletextension/api/static/favicon.ico b/tools/walletextension/api/static/favicon.ico new file mode 100644 index 0000000000..1bb8f324a1 Binary files /dev/null and b/tools/walletextension/api/static/favicon.ico differ diff --git a/tools/walletextension/api/static/index.html b/tools/walletextension/api/static/index.html deleted file mode 100644 index 8bdd8fb131..0000000000 --- a/tools/walletextension/api/static/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Obscuro | Generate viewing key - - - - - - - - -

◠. Hello frens. Welcome to the Obscuro wallet extension! ◠.

- - - -

- - - \ No newline at end of file diff --git a/tools/walletextension/api/static/javascript.js b/tools/walletextension/api/static/javascript.js deleted file mode 100644 index b57d372df1..0000000000 --- a/tools/walletextension/api/static/javascript.js +++ /dev/null @@ -1,77 +0,0 @@ -const eventClick = "click"; -const eventDomLoaded = "DOMContentLoaded"; -const idGenerateViewingKey = "generateViewingKey"; -const idStatus = "status"; -const pathGenerateViewingKey = "/generateviewingkey/"; -const pathSubmitViewingKey = "/submitviewingkey/"; -const methodPost = "post"; -const jsonHeaders = { - "Accept": "application/json", - "Content-Type": "application/json" -}; -const metamaskRequestAccounts = "eth_requestAccounts"; -const metamaskPersonalSign = "personal_sign"; -const personalSignPrefix = "vk"; - -const initialize = () => { - const generateViewingKeyButton = document.getElementById(idGenerateViewingKey); - const statusArea = document.getElementById(idStatus); - - generateViewingKeyButton.addEventListener(eventClick, async () => { - if (typeof ethereum === "undefined") { - statusArea.innerText = "`ethereum` object is not available. Please install and enable MetaMask." - return - } - - const accounts = await ethereum.request({method: metamaskRequestAccounts}); - if (accounts.length === 0) { - statusArea.innerText = "No MetaMask accounts found." - return - } - // Accounts is "An array of a single, hexadecimal Ethereum address string.", so we grab the single entry at index zero. - const account = accounts[0]; - - const addressJson = {"address": account} - const viewingKeyResp = await fetch( - pathGenerateViewingKey, { - method: methodPost, - headers: jsonHeaders, - body: JSON.stringify(addressJson) - } - ); - if (!viewingKeyResp.ok) { - statusArea.innerText = "Failed to generate viewing key." - return - } - - const viewingKey = await viewingKeyResp.text(); - - const signature = await ethereum.request({ - method: metamaskPersonalSign, - // Without a prefix such as 'vk', personal_sign transforms the data for security reasons. - params: [personalSignPrefix + viewingKey, account] - }).catch(_ => { return -1 }) - if (signature === -1) { - statusArea.innerText = "Failed to sign viewing key." - return - } - - const signedViewingKeyJson = {"signature": signature, "address": account} - const submitViewingKeyResp = await fetch( - pathSubmitViewingKey, { - method: methodPost, - headers: jsonHeaders, - body: JSON.stringify(signedViewingKeyJson) - } - ); - - let checksummedAccount = Web3.utils.toChecksumAddress(account); - if (submitViewingKeyResp.ok) { - statusArea.innerText = `Account: ${checksummedAccount}\nViewing key: ${viewingKey}\nSigned bytes: ${signature}` - } else { - statusArea.innerText = "Failed to submit viewing key to enclave." - } - }) -} - -window.addEventListener(eventDomLoaded, initialize); \ No newline at end of file diff --git a/tools/walletextension/api/static/style.css b/tools/walletextension/api/static/style.css deleted file mode 100644 index 2c9cadb9cd..0000000000 --- a/tools/walletextension/api/static/style.css +++ /dev/null @@ -1,34 +0,0 @@ -html { - font-family: sans-serif; - line-height: 1.5; -} - -body { - color: white; - background-color: black; - margin: 1rem; -} - -a { - color: white; -} - -textarea { - color: white; - background-color: black; - font-family: sans-serif; - border: solid 1px white; - border-radius: 3px; -} - -button { - color: white; - background-color: black; - border: solid 1px white; - border-radius: 3px; -} - -/*Formats the block-decoder form.*/ -form { display: table; } -label { display: table-cell; } -input { display: table-cell; } \ No newline at end of file diff --git a/tools/walletextension/frontend/next.config.js b/tools/walletextension/frontend/next.config.js index a843cbee09..45ddca84d4 100644 --- a/tools/walletextension/frontend/next.config.js +++ b/tools/walletextension/frontend/next.config.js @@ -1,6 +1,8 @@ /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, + output: 'export', + distDir: '../api/static' } module.exports = nextConfig diff --git a/tools/walletextension/frontend/src/components/modules/common/network-status.tsx b/tools/walletextension/frontend/src/components/modules/common/network-status.tsx index bfa457bfa2..8f999f4015 100644 --- a/tools/walletextension/frontend/src/components/modules/common/network-status.tsx +++ b/tools/walletextension/frontend/src/components/modules/common/network-status.tsx @@ -8,7 +8,7 @@ const MessageContent = ( ); export const NetworkStatus = ({ message = MessageContent }) => { - const [isOnline, setIsOnline] = React.useState(navigator.onLine); + const [isOnline, setIsOnline] = React.useState(true); React.useEffect(() => { const setOnlineStatus = () => { diff --git a/tools/walletextension/main/main.go b/tools/walletextension/main/main.go index 119a3d707c..63c8234069 100644 --- a/tools/walletextension/main/main.go +++ b/tools/walletextension/main/main.go @@ -74,7 +74,7 @@ func main() { }() walletExtensionAddr := fmt.Sprintf("%s:%d", common.Localhost, config.WalletExtensionPortHTTP) - fmt.Printf("💡 Wallet extension started - visit http://%s/viewingkeys/ to generate an ephemeral viewing key.\n", walletExtensionAddr) + fmt.Printf("💡 Wallet extension started") // Some tests rely on seeing this message. Removed in next PR. fmt.Printf("💡 Obscuro Gateway started - visit http://%s to use it.\n", walletExtensionAddr) select {}