使用 Nodejs、MetaMask 和 OpenSea 来进行 NFT登录

news/2024/7/4 1:44:18

使用 Nodejs、MetaMask 和 OpenSea 来进行 NFT登录

未标题-3

img

假设我们想要构建一个应用程序,其中只有来自特定集合的NFT的所有者才能登录。

需要使用的技术:

  • Nodejs用于后端/API。
  • 用于客户端登录的Metamask。
  • 用于NFT所有权验证的OpenSea API。

这是Authenticating users to your web app using metamask and nodejs一文的后续,所有基本的元掩码登录代码都在该文章中共享。链接:https://blog.devgenius.io/authenticating-users-to-your-web-app-using-metamask-and-nodejs-e920e45e358

下面是我们想要实现的流程:

img

我们将使用OpenSea API作为例子。

OpenSea API

OpenSea为开发人员提供了一个API来与他们的数据进行交互。我们可以在没有任何额外设置的情况下发出请求,但为了在实际应用程序中调用API,我们需要获得一个API密钥。可以在这里请求一个API密钥:

https://docs.opensea.io/reference/request-an-api-key

我们将使用资产端点来检索钱包拥有的NFT。可以在这里找到这个端点的完整信息:

https://docs.opensea.io/reference/getting-assets

要获取集合ID,我们可以直接在OpenSea文档页面上运行以下端点:

https://docs.opensea.io/reference/retrieving-a-single-asset

img

我们想要得到的值是" slug ":

img

所以,在这个例子中,我们可以这样请求:

GET https://api.opensea.io/api/v1/assets?owner=userWalletAddress&collection=boredapeyatchclub

img

端点将返回我们提供的 NFT 集合中用户拥有的所有 NFT。如果返回任何NFT,这意味着用户可以继续登录过程,否则,他将无法继续。

后端端点

下面的代码片段中可以找到实现此流程的Nodejs的工作代码片段。可以在下面链接中找到这个示例的所有其他代码片段。https://blog.devgenius.io/authenticating-users-to-your-web-app-using-metamask-and-nodejs-e920e45e358

// Process signed message
router.post('/:user/signature', (req, res) => {
    // Get user from db
    db.get('SELECT * FROM users WHERE address = ?', [req.params.user], (err, row) => {
        if (err) {
            console.error(err.message);
            return res.status(500).send(err.message);
        }
        if (row) {
            const msg = `Nonce: ${row.nonce}`;
            console.log("User nonce from db: " + row.nonce);
            // Convert msg to hex string
            const msgHex = ethUtil.bufferToHex(Buffer.from(msg));

            // Check if signature is valid
            const msgBuffer = ethUtil.toBuffer(msgHex);
            const msgHash = ethUtil.hashPersonalMessage(msgBuffer);
            const signatureBuffer = ethUtil.toBuffer(req.body.signature);
            const signatureParams = ethUtil.fromRpcSig(signatureBuffer);
            const publicKey = ethUtil.ecrecover(
                msgHash,
                signatureParams.v,
                signatureParams.r,
                signatureParams.s
            );
            const addressBuffer = ethUtil.publicToAddress(publicKey);
            const address = ethUtil.bufferToHex(addressBuffer);
            
            console.log("Decrypted address: " + address);
            console.log("User address: " + req.params.user);

            // Check if address matches
            if (address.toLowerCase() === req.params.user.toLowerCase()) {
                // Run NFT ownership check if env flag is enabled
                if (process.env.RESTRICT_BY_NFT_COLLECTION == "true") {
                    request.get(`https://api.opensea.io/api/v1/assets?owner=${req.params.user}&collection=${process.env.NFT_COLLECTION_SLUG}`, (err, response, body) => {
                        if (err) {
                            console.error(err.message);
                            return res.status(500).send(err.message);
                        }
                        if (response.statusCode == 200) {
                            if (JSON.parse(body).assets.length >= 0) {
                                console.log("User owns NFT from collection - access granted");

                                // Update user nonce
                                var newNonce = Math.floor(Math.random() * 1000000);
                                db.run('UPDATE users SET nonce = ? WHERE address = ?', [newNonce, req.params.user], (err) => {
                                    if (err) {
                                        console.error(err.message);
                                        return res.status(500).send(err.message);
                                    }
                                    // Set jwt token
                                    const token = jwt.sign({
                                        address: req.params.user,
                                        nonce: newNonce
                                    }, process.env.JWT_SECRET);
                                    return res.status(200).send({
                                        success: true,
                                        token: `Bearer ${token}`,
                                        user: row,
                                        msg: "You are now logged in."
                                    });
                                });

                            } else {
                                console.log("User does not own NFT from collection - access denied");
                                return res.status(403).send("User does not own NFT from collection");
                            }
                        } else {
                            console.log("User does not own NFT from collection");
                            return res.status(403).send("User does not own NFT from collection");
                        }
                    });
                }

                if (process.env.RESTRICT_BY_NFT_COLLECTION == "false") {
                    // Update user nonce
                    var newNonce = Math.floor(Math.random() * 1000000);
                    db.run('UPDATE users SET nonce = ? WHERE address = ?', [newNonce, req.params.user], (err) => {
                        if (err) {
                            console.error(err.message);
                            return res.status(500).send(err.message);
                        }
                        // Set jwt token
                        const token = jwt.sign({
                            address: req.params.user,
                            nonce: newNonce
                        }, process.env.JWT_SECRET);
                        return res.status(200).send({
                            success: true,
                            token: `Bearer ${token}`,
                            user: row,
                            msg: "You are now logged in."
                        });
                    });
                }
            } else {
                return res.status(401).send({
                    success: false,
                    msg: "Signature is invalid."
                });
            }
        } else {
            console.log('User does not exist');
            return res.status(404).send('User not found');
        }
    });
});

结论

这篇文章是一个简短而实用的教程,教我们如何在web应用中快速实现基于NFT所有权的认证。如果我们被卡住了,或者想要进一步理解上面提到的一些主题,我们可以看看这些资源:

  • OpenSea api 文档
  • SQLite 入门
  • Metamask 开发者文档
  • 使用 Metamask 创建一个基本的去中心化应用程序
  • 使用 express 创建 nodejs 应用程序
  • 使用 passport-jwt 库生成 jwt 令牌

Source:https://medium.com/@duartefdias/nft-login-with-nodejs-metamask-and-opensea-1ae3b49769bc

关于

ChinaDeFi - ChinaDeFi.com 是一个研究驱动的DeFi创新组织,同时我们也是区块链开发团队。每天从全球超过500个优质信息源的近900篇内容中,寻找思考更具深度、梳理更为系统的内容,以最快的速度同步到中国市场提供决策辅助材料。

Layer 2道友 - 欢迎对Layer 2感兴趣的区块链技术爱好者、研究分析人与Gavin(微信: chinadefi)联系,共同探讨Layer 2带来的落地机遇。敬请关注我们的微信公众号 “去中心化金融社区”

img


http://www.niftyadmin.cn/n/4585940.html

相关文章

菱形虚拟继承虚函数表对象模型

菱形继承:Assitant的菱形继承对象模型Assitant中有两份Person成员,存在二义性和数据冗余。所以我们引出了虚拟继承。virtual虚继.不会在子类中创建父类成员,但是子类中可以引用,就像指针一样。主要用在菱形继承,也叫钻…

cmder中git log 文乱码

2019独角兽企业重金招聘Python工程师标准>>> 打开设置; Startup-Environment; 添加 set LANGzh_CN.UTF-8 git status时中文文件名乱码 现象: \344\275\240\345\245\275执行以下命令即可: git config --global core.quotepath false quotepath…

题解 P1434 【滑雪】

题目链接 此题运用功能强大的 ~~暴力搜索~~ 记忆化搜索才是重点!!! 然而,这是一道经典的DP问题 如果我们用$dis[i][j]$来表示坐标为$(i,j)$时的高度 $cnt[i][j]$ 是我们的记忆化数组 在合法的前提下,就有状态转移方程…

加密领域第一季度回顾和市场展望

加密领域第一季度回顾和市场展望 快览: 尽管市场低迷,但加密投资在第一季度仍然非常活跃。在基础设施方面,我们在跨链解决方案和DAO工具中看到了很多的动向。新的 layer-1仍在孵化中。在以太坊上开发的DeFi原语正在扩展到更新的L1&#xff0…

hadoop2-shell操作详解

转载之&#xff1a;https://www.cnblogs.com/870386641drh/p/4262593.html FS Shell调用文件系统(FS)Shell命令应使用 bin/hadoop fs <args>的形式。 所有的的FS shell命令使用URI路径作为参数。URI格式是scheme://authority/path。对HDFS文件系统&#xff0c;scheme是hd…

Android apk程序调用其它的APK程序

Intent mIntent new Intent(); ComponentName comp new ComponentName("启动的APK包名","启动的APK入口类&#xff08;包名加类名&#xff09;"); mIntent.setComponent(comp); mIntent.setAction("android.intent.action.MAIN"); startActivi…

如何使用 Solidity 编写 PayNow 函数?

如何使用 Solidity 编写 PayNow 函数&#xff1f; 介绍 web3经济正在蓬勃发展&#xff0c;学习这项技术的最佳时机就是现在。我们不能错过对web3开发者的全球需求。 区块链开发人员的平均年薪大约是146250美元&#xff0c;这是其他软件开发职业中最高的。 现在对web3开发人员…

红杉、IDG、北极光、顺为等投资大咖怎么看智能硬件

回顾2015年的智能硬件领域创业&#xff0c;谷歌、 Facebook、微软等国际巨头&#xff0c;BAT等国内大佬都争相角逐&#xff0c;智能硬件的上下游产业链及行业生态已经开始形成&#xff0c;巨头们的领跑将开启智能硬件一个新的时代。让我们来看看&#xff0c;智能硬件领域的投资…