首页 > 数据库 >同步合约数据到数据库经典案例2

同步合约数据到数据库经典案例2

时间:2023-04-12 18:01:26浏览次数:35  
标签:COMMENT 同步 utf8mb4 DEFAULT 数据库 案例 meta let NULL

在上一篇文章中,我们从event log中同步数据。本篇我们尝试直接调用合约来获取数据。

在我们的示例合约中,定义了一个struct用来保存数字藏品的上架信息。

```javascript

struct salesInfo {
   address sales;
   address collection;
   uint96 token_id;
   address token;
   uint128 price;
   uint64 duetime;
   address seller;
}
    
```

同时定义了一个function getSales()用来返回全部的商品列表信息。

原本这样一个商品列表就可以支持用户进行数字藏品交易了。但是我们发现,藏品列表过于简单,不支持排序功能。既不支持按商品价格排序,更别提要支持上架时间排序了。

轮到我们数据同步程序以及中间件接口发挥光芒的时刻了。先上代码:syncMarket.js

```javascript

const { ethers } = require("hardhat");
var mysql = require("mysql");
let dotenv = require('dotenv')
dotenv.config({ path: "./.env" })

var connection = mysql.createConnection({
  host: process.env.MYSQL_HOST,
  port: process.env.MYSQL_PORT,
  user: process.env.MYSQL_USER,
  password: process.env.MYSQL_PASSWORD,
  database: process.env.MYSQL_DATABASE,
  charset: process.env.MYSQL_CHARSET
});

function DbQuery(sqlstr, values = null) {
  return new Promise((resolve, reject) => {
    connection.query(sqlstr, [values], (error, results) => {
      if (error) {
        reject(error);
      } else {
        resolve(results);
      }
    });
  });
}

async function main() {
  let values = [];
  let [owner] = await ethers.getSigners();
  let addr = ""; // metaMasterAddress
  let meta = await ethers.getContractAt("metaMaster", addr, owner);
  let SalesCount = await meta.getSalesCount();
  let nftsInSale = await meta.getSales(SalesCount, 0);
  let nftsInSaleArr = Object.values(nftsInSale);

  nftsInSaleArr.forEach(element => {
    values.push([element.sales, element.collection, element.token_id, element.token, element.price, element.duetime, element.seller]);
  });
  if (values.length > 0) {
    let sqlstr = "insert into meta_market (`sales`,`collection`,`tokenID`,`token`,`price`,`duetime`,`seller`) values ? on duplicate key update sales=values(sales), token=values(token), price=values(price), duetime=values(duetime), seller=values(seller)";
    let s = await DbQuery(sqlstr, nftsInSale);
    console.log(s);
  }
}

main()
  .then(() => {
    connection.end();
    process.exit(0);
  })
  .catch(error => {
    console.error(error);
    process.exit(1);
  })
  
```

如何使用dotenv读取环境变量,如何连接MySQL,以及async类型的main方法的相关知识,上次已经讲过了,本文略过不提。

连接区块链依然主要通过ethers库来实现。

从区块链读取event logs使用ethers.provider.getLogs()方法,而读取合约更加直接,连接上合约实例,直接调用合约方法即可。

即如果合约有getSales方法,js里就用合约实例meta直接调用meta.getSales()方法,如代码解释第3步。代码解释如下:

```javascript

// 1. 连接合约
let meta = await ethers.getContractAt("metaMaster", addr, owner);
// 2. 调用合约,获取当前商品数量
let SalesCount = await meta.getSalesCount();
// 3. 调用合约,获取当前商品列表
let nftsInSale = await meta.getSales(SalesCount, 0);
// 4. 将返回值从object转化为array
let nftsInSaleArr = Object.values(nftsInSale);

```

至此,我们将当前所有货架上的商品信息全部存入数据库。而列表按价格排序,已经很容易实现了。现附market表的数据结构一份,如下:

```sql

CREATE TABLE `meta_market` (
  `sales` char(42) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0x' COMMENT '销售合约(一口价/拍卖)',
  `collection` char(42) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0x' COMMENT 'nft合约地址',
  `tokenID` int unsigned NOT NULL DEFAULT '0' COMMENT 'tokenID',
  `token` char(42) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0x' COMMENT '付款代币合约地址',
  `price` decimal(65,0) unsigned NOT NULL DEFAULT '0' COMMENT '报价',
  `duetime` int unsigned NOT NULL DEFAULT '0' COMMENT '到期时间',
  `seller` char(42) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0x' COMMENT '卖家',
  `updateTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`collection`,`tokenID`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC


```

有细心的网友已经看出来了,数据库此时并没有记录商品的上架时间。也就是说我们暂时还不能够按照商品上架时间给列表进行排序。

在上一篇文章我们有提到过,示例合约有5种事件类型。其中ConfirmSale对应order表,而CreateSale就可以对应market表。

```javascript

event CreateSale(address indexed _contract, uint _tokenId, address seller, address token, uint _price, uint _due);

```

貌似通过CreateSale日志,我们也能够获得market列表,为什么我们选择了直接从合约读取呢?此处留下包袱,后续再翻出。

接下来我们先定义一张新表,用于保存示例合约的全部event logs

```sql

CREATE TABLE `meta_activity` (
  `event` varchar(11) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '事件名',
  `txType` smallint DEFAULT '1' COMMENT '交易类型:1.一口价;2.拍卖;',
  `contract` char(42) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'nft合约地址',
  `tokenID` int NOT NULL COMMENT 'tokenID',
  `from` char(42) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '卖家',
  `to` char(42) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '买家',
  `token` char(42) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '代币合约地址',
  `price` decimal(65,0) NOT NULL COMMENT '价格',
  `duetime` int unsigned DEFAULT NULL COMMENT '到期时间',
  `blocknum` int NOT NULL COMMENT '交易所在区块号',
  `txhash` char(66) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '交易哈希',
  `timestamp` int NOT NULL COMMENT '交易区块对应的时间戳',
  `dt` char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '""' COMMENT '交易日期',
  `h` int NOT NULL COMMENT '交易小时数',
  PRIMARY KEY (`txhash`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC

```

如何将event log同步到数据库,我们上一篇已经讲过,本次略过不提。

通过activity表,我们可以找出每一个数字藏品的最新上架时间,即便该商品曾经多次上架。也正式因为某些藏品存在多次上架的情况,我们才没有第一时间选取通过event logs来获取market列表。

```sql

SELECT 
  `b`.`contract` AS `contract`,
  `b`.`tokenID` AS `tokenID`,
  `b`.`blocknum` AS `blocknum`,
  `b`.`timestamp` AS `timestamp`,
  `b`.`rn` AS `rn` 
FROM
  (SELECT 
    `nft_mall`.`meta_activity`.`contract` AS `contract`,
    `nft_mall`.`meta_activity`.`tokenID` AS `tokenID`,
    `nft_mall`.`meta_activity`.`blocknum` AS `blocknum`,
    `nft_mall`.`meta_activity`.`timestamp` AS `timestamp`,
    row_number () OVER (
      PARTITION BY `nft_mall`.`meta_activity`.`contract`,
      `nft_mall`.`meta_activity`.`tokenID` 
  ORDER BY `nft_mall`.`meta_activity`.`blocknum` DESC
  ) AS `rn` 
  FROM
    `nft_mall`.`meta_activity` 
  WHERE (
      `nft_mall`.`meta_activity`.`event` = 'CreateSale'
    )) `b` 
WHERE (`b`.`rn` = 1)

```

此处蕴含知识点,over()函数的使用。通过over()函数,我们按数据表的合约地址和tokenID进行了分组。同时按照CreateSale事件日志的区块号进行了倒序排序。

通过row_number()函数给分组内的每一条记录增加了序号。而通过再次select选择,找出来每一组(即每一个数字藏品)的最新上架时间。

我们将该语句保存为视图 meta_view_create_latest。

中间件接口在返回market list时,可联表查询查询获得该藏品的上架时间。如为提高查询性能,也可将结果直接保存在market表中。

至此我们已经可以实现按藏品上架的时间进行排序返回列表了。

标签:COMMENT,同步,utf8mb4,DEFAULT,数据库,案例,meta,let,NULL
From: https://blog.51cto.com/u_16028817/6186018

相关文章

  • 图数据库驱动的基础设施运维实操
    本文系图技术在大型、复杂基础设施之中SRE/DevOps的实践参考,并以OpenStack系统之上的图数据库增强的运维案例为例,揭示图数据库、图算法在智能运维上的应用。本文所有示例代码开源。最近,有些尚未使用过图技术、DevOps/Infra领域的工程师在NebulaGraph社区询问是否有「图......
  • 服务器节点之间 如何实现自动化文件同步?
    大数据、云计算、物联网的发展,使得企业能够拥有的数据急剧增加。面对快速变化和增长的庞大数据,如何高效地管理、利用数据对于企业来说至关重要。但是,数据传输模式单一、自动化程度低、传输效率低下等难题,阻碍着企业对其数字资产的管控和利用,也制约了企业运营效率的提升。 很显......
  • 基于chunjun纯钧的增量数据同步问题排查【博客园-实习小生】
    基于chunjun纯钧的增量数据同步目前我司的大数据平台使用的是flink技术栈,底层的连接器插件使用的是国产的chunjun插件,在使用chunjun的过程中也遇到了很多问题,本次记录下在SQL模式的情况下怎么支持增量的数据同步chunjun的官网文档对增量同步已经做出了一定的说明纯钧官方根......
  • 使用MySql8.0+项目无法连接数据库问题
    MySql连接字符串:jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai注意这里的useSSL为true:表示使用安全连接经过查阅网络博客发现将useSSL修改为false可以正常连接具体原因之后更新......
  • java项目 学生成绩管理系统 (源码+数据库文件)
    ​ 需要的私信我备注来意:项目名称来了就点个赞再走呗,即将毕业的兄弟有福了文章底部获取源码java项目  学生成绩管理(源码+数据库文件)技术框架:java+springboot+vue+mysql后端框系统共分为三种用户系统主要功能:系统设计三个角色,学生端,教师端,系统管理员端一、系统运行......
  • nodejs连接mysql数据库
      https://www.cnblogs.com/hechunfeng/p/17308654.html这个是安装数据库   1.我们先建一个表和插入一下字段,这些都是自己弄的    2.安装npminstallmysqlconst{createPool}=require('mysql');constpool=createPool({host:"localhost",......
  • 记一次kvm虚机mysql数据库磁盘扩容操作步骤及其问题小坑
    背景:业务量持续增加,原来规划的1T磁盘空间不足以支撑业务发展存储使用,需要对数据库磁盘进行扩容。目前物理机有新增了2块3.5Tssd的数据盘用于数据库虚机磁盘扩容使用。需要安排时间对其进行操作扩容。操作思路:1、完成磁盘raid1操作,将新磁盘挂载到物理机上并添加到kvm的存储空间......
  • 利用hibernate分析数据库中的表,属性以及对应的类的类名,字段
    2010-08-1109:27hibernate获得数据库的表名列名及其数据@TestpublicvoidtestHIbernateConfig1(){SessionFactoryfactory=newAnnotationConfiguration().configure().buildSessionFactory();AbstractEntityPersisterclassMetadata=......
  • mysql安装和nodejs连接数据库
      mysql下载地址https://dev.mysql.com/downloads/installer/        第一步,安装自定义   2.添加这三个产品   3.下一步   4.默认端口3306,如果被占用了就自己改下    5.强密码认证   6,添加密码和用户,密码......
  • 【Serverless】云数据库端云一体化问题
     【关键字】AGC、HarmonyOS、端云一体化 【问题描述】开发者反馈在鸿蒙应用集成了AGC云数据库服务,在引入AGC服务时遇到了一些问题。具体如下所述:1、HarmonyOSArkTS语言开发,参数是number类型,但是查询的云数据库字段是Integer类型,这要怎么处理。2、样例中querybook的字段b......