DEV Community

Mark Okhman
Mark Okhman

Posted on • Edited on

3

Using DeLab Connect with Next.js

Recently I've seen a release of an awesome repository enabling single-page React apps to seamlessly integrate authentication with a number of TON wallets.

Kudos to DeLab team ❤️
https://github.com/delab-team/connect

I plan to record a video soon where I will go into more detail on when this is a good lib to use and when we should go with the standard "per-wallet" authentication approach. Subscribe to my Telegram channel if you don't want to miss it https://t.me/markokhmandev

Because I'm using Next.js for most of my web projects, I've run into some issues using DeLab Connect. However, a single React hook solves those issues. This hook makes sure that we are importing the DeLab Connect only on the client side. Furthermore, our hook has an interface (connectInfo and callbacks) to interact with the DeLab Connect instance.

Before we get to the hook's code, let's do some preparation. You will need to prepare the delab's module before passing it to Next.js. For this you need two things:

  • Install next-transpile-modules:
yarn add next-transpile-modules
Enter fullscreen mode Exit fullscreen mode
  • Replace default next.config.js with following code:
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
};
const withTM = require("next-transpile-modules")(["@delab-team/connect"]); // pass the modules you would like to see transpiled
module.exports = withTM(nextConfig);
Enter fullscreen mode Exit fullscreen mode

Now we are good to go with the Hook's code:

import { DeLabEvent, DeLabNetwork } from "@delab-team/connect";
import { createElement, useEffect, useState } from "react";
export const useDeLabConnect = (props: {
connectInfo: {
url: string;
name: string;
network: DeLabNetwork;
};
callbacks: {
onConnect?: (event: DeLabEvent) => void;
onDisconnect?: () => void;
onApproveLink?: (event: DeLabEvent) => void;
onError?: (event: DeLabEvent) => void;
onErrorTransaction?: (event: DeLabEvent) => void;
onErrorTonCoinWallet?: (event: DeLabEvent) => void;
onErrorTonhub?: (event: DeLabEvent) => void;
onErrorTonkeeper?: (event: DeLabEvent) => void;
};
}) => {
const [DeLabConnector, setDeLabConnector] = useState<any>();
const [DeLabModal, setDeLabModal] = useState<any>(null);
const [DeLabButton, setDeLabButton] = useState<any>(null);
useEffect(() => {
(async () => {
if (typeof window !== "undefined") {
const DeLab = await import("@delab-team/connect");
const DeLabConnector = new DeLab.DeLabConnect(
props.connectInfo.url,
props.connectInfo.name,
props.connectInfo.network
);
setDeLabConnector(DeLabConnector);
setDeLabModal(
createElement(DeLab.DeLabModal, {
DeLabConnectObject: DeLabConnector,
scheme: "dark",
})
);
setDeLabButton(
createElement(DeLab.DeLabButton, {
DeLabConnectObject: DeLabConnector,
scheme: "dark",
})
);
DeLabConnector.on("connect", async (event: DeLabEvent) =>
props.callbacks.onConnect?.(event)
);
DeLabConnector.on("disconnect", () => {
props.callbacks.onDisconnect?.();
});
DeLabConnector.on("approve-link", (event: DeLabEvent) => {
props.callbacks.onApproveLink?.(event);
});
DeLabConnector.on("error", (event: DeLabEvent) => {
props.callbacks.onError?.(event);
});
DeLabConnector.on("error-transaction", (event: DeLabEvent) => {
props.callbacks.onErrorTransaction?.(event);
});
DeLabConnector.on("error-toncoinwallet", (event: DeLabEvent) => {
props.callbacks.onErrorTonCoinWallet?.(event);
});
DeLabConnector.on("error-tonhub", (event: DeLabEvent) => {
props.callbacks.onErrorTonhub?.(event);
});
DeLabConnector.on("error-tonkeeper", (event: DeLabEvent) => {
props.callbacks.onErrorTonkeeper?.(event);
});
DeLabConnector.loadWallet();
}
})();
}, []);
return { DeLabConnector, DeLabModal, DeLabButton };
};

You can place this hook anywhere in your project (ex. /shared/hooks/useDeLabConnect.ts) and then import it on your page.

How do we use it?

Inside of our page component we are placing the use of our hook:

 const { DeLabConnector, DeLabModal, DeLabButton } = useDeLab({
    connectInfo: {
      url: "https://example.com",
      name: "Example",
      network: "testnet",
    },
    callbacks: {
      onConnect: async (event: DeLabEvent) => handleConnect(event),
      onDisconnect: () => {
        console.log("disconect");
      },
      onErrorTransaction: (event: DeLabEvent) => handleErrorTransaction(event),
      // ... other callbacks handled in our hook
    },
  });
Enter fullscreen mode Exit fullscreen mode

Our hook returns 3 important instances:
DeLabConnector - of type DeLabConnect, we will use this one to request transactions etc.
DeLabModal & DeLabButton - Elements, we will simply put them on the page

Here is a full example of our Next.js page using the useDeLabConnect.ts

import {
DeLabConnecting,
DeLabEvent,
DeLabTransaction,
} from "@delab-team/connect";
import { useState } from "react";
import { useDeLab } from "../shared/DeLabHook";
export default function Home() {
const [isConnected, setIsConnected] = useState(false);
const [connectConfig, setConnectConfig] = useState<DeLabConnecting>();
const { DeLabConnector, DeLabModal, DeLabButton } = useDeLab({
connectInfo: {
url: "https://example.com",
name: "Example",
network: "testnet",
},
callbacks: {
onConnect: async (event: DeLabEvent) => handleConnect(event),
onDisconnect: () => {
console.log("disconect");
},
onErrorTransaction: (event: DeLabEvent) => handleErrorTransaction(event),
// ... other callbacks handled in our hook
},
});
const handleConnect = async (event: DeLabEvent) => {
setIsConnected(true);
setConnectConfig(event.data);
};
const handleErrorTransaction = async (event: DeLabEvent) => {
console.log("error transaction", event.data);
};
const triggerDisconnect = async () => {
await DeLabConnector!.disconnect();
setIsConnected(false);
};
const triggerRequestTransaction = async () => {
const trans: DeLabTransaction = {
to: "EQCkR1cGmnsE45N4K0otPl5EnxnRakmGqeJUNua5fkWhales",
value: "1000000", // string value in nano-coins
};
const data = await DeLabConnector!.sendTransaction(trans);
if (connectConfig!.typeConnect === "tonkeeper") {
// display qrcode code ...
console.log("tonkeeper link: ", data);
}
};
return (
<div>
{DeLabModal}
{isConnected ? (
<>
<p>Connected</p>
<button onClick={triggerDisconnect}>Disconnect</button>
<button onClick={triggerRequestTransaction}>
Request transaction
</button>
</>
) : (
DeLabButton
)}
</div>
);
}
view raw Home.tsx hosted with ❤ by GitHub

That's it :) Let me know in comments, what you think about this.
And bro, please subscribe to my Telegram channel: https://t.me/markokhmandev

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay