Hashpack / hashconnect

Hashconnect library, readme in progress
BSD Zero Clause License
45 stars 38 forks source link

TypeError: bufferUtil.mask is not a function #202

Open samuelnihoul opened 5 months ago

samuelnihoul commented 5 months ago
TypeError: bufferUtil.mask is not a function
    at module.exports.mask (webpack-internal:///(ssr)/./node_modules/ws/lib/buffer-util.js:96:29)
    at Sender.frame (webpack-internal:///(ssr)/./node_modules/ws/lib/sender.js:117:9)
    at Sender.dispatch (webpack-internal:///(ssr)/./node_modules/ws/lib/sender.js:360:35)
    at Sender.send (webpack-internal:///(ssr)/./node_modules/ws/lib/sender.js:321:22)
    at WebSocket.send (webpack-internal:///(ssr)/./node_modules/ws/lib/websocket.js:366:22)
    at WebSocketRelay.subscribe (webpack-internal:///(ssr)/./node_modules/hashconnect/dist/esm/types/relay.js:68:21)
    at HashConnect.connect (webpack-internal:///(ssr)/./node_modules/hashconnect/dist/esm/hashconnect.js:113:26)
    at eval (webpack-internal:///(ssr)/./node_modules/hashconnect/dist/esm/hashconnect.js:69:42)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Happens with hashconnect v.0.2 and ws v.8.16 or greater. To reproduce, use Next.js 14 because it's a server-side log only. Here is my "HashButton" component:

'use client'
import { ContentCopy } from "@mui/icons-material";
import {
    Box,
    Button,
    Dialog,
    IconButton,
    Snackbar,
    Stack,
    TextField,
} from "@mui/material";
import { useCallback, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getPairingData, hc, hcInitPromise } from "../lib/hashconnect";
import { actions, AppStore } from "../store";
import React from 'react'

export const HashConnectClient = () => {
    const dispatch = useDispatch();
    const syncWithHashConnect = useCallback(() => {
        const pairingData = getPairingData();
        if (pairingData) {
            dispatch(actions.hashconnect.setAccountIds(pairingData.accountIds));
            dispatch(actions.hashconnect.setIsConnected(true));
            dispatch(actions.hashconnect.setPairingString(hc.hcData.pairingString));
        } else {
            dispatch(actions.hashconnect.setAccountIds([]));
            dispatch(actions.hashconnect.setIsConnected(false));
            dispatch(actions.hashconnect.setPairingString(hc.hcData.pairingString));
        }
    }, [dispatch]);

    syncWithHashConnect();
    hcInitPromise.then(() => {
        syncWithHashConnect();
    });
    hc.pairingEvent.on(() => {
        syncWithHashConnect();
    });
    hc.connectionStatusChangeEvent.on(() => {
        syncWithHashConnect();
    });
    return null;
};

export default function HashConnectConnectButton() {
    const {
        isConnected,
        accountIds: connectedAccountIds,
        pairingString,
    } = useSelector((state: AppStore) => state.hashconnect);

    const [open, setOpen] = useState(false);
    useEffect(() => {
        if (isConnected) {
            setOpen(false);
        }
    }, [isConnected]);

    const [snackbarOpen, setSnackbarOpen] = useState(false);

    let connectButtonText = "Hashpack Connect";
    if (isConnected) {
        if (connectedAccountIds.length > 1) {
            connectButtonText = `Disconnect Accounts`;
        } else {
            connectButtonText = `Disconnect Account`;
        }
    }

    return (
        <Box>
            <button
                className="bg-purple-500 px-[1rem] py-[0.5rem] rounded-md"
                onClick={async () => {
                    if (isConnected) {
                        await hcInitPromise;
                        if (isConnected) {
                            const pairingData = getPairingData();
                            if (pairingData) {
                                hc.disconnect(pairingData.topic);
                            }
                        }
                    } else {
                        setOpen(true);
                    }
                }}
            >
                {connectButtonText}
            </button>

            <Dialog
                open={open}
                onClose={() => {
                    setOpen(false);
                }}
            >
                <Snackbar
                    anchorOrigin={{ vertical: "top", horizontal: "center" }}
                    open={snackbarOpen}
                    autoHideDuration={3000}
                    onClose={() => {
                        setSnackbarOpen(false);
                    }}
                >
                    <Box
                        sx={{
                            bgcolor: "success.main",
                            color: "white",
                            p: 2,
                            borderRadius: 1,
                        }}
                    >
                        Copied to clipboard!
                    </Box>
                </Snackbar>
                <Stack maxWidth="800px" spacing={4} p={4}>
                    <Button
                        color={"blurple" as any}
                        variant="contained"
                        onClick={async () => {
                            await hcInitPromise;
                            hc.connectToLocalWallet();
                        }}
                    >
                        Connect to Local Wallet
                    </Button>

                    <TextField
                        variant="standard"
                        color={"blurple" as any}
                        value={pairingString}
                        contentEditable={false}
                        label="Pairing String"
                        // add end adornment to copy the pairing string
                        InputProps={{
                            endAdornment: (
                                // replace the below button with a copy to clipboard button icon
                                <IconButton
                                    color={"blurple" as any}
                                    onClick={() => {
                                        navigator.clipboard
                                            .writeText(pairingString)
                                            .then(() => {
                                                setSnackbarOpen(true);
                                            })
                                            .catch((reason) => {
                                                console.error(
                                                    `Failed to copy pairing string: ${reason}`
                                                );
                                            });
                                    }}
                                >
                                    <ContentCopy />
                                </IconButton>
                            ),
                        }}
                    />
                </Stack>
            </Dialog>
        </Box>
    );
};