项目背景
在做海外NFT相关的业务中,我们难免需要使用到各类NFT相关的数据提供给我们自己系统的用户使用,但是区块链节点API并不提供结构化查询接口,已知的第三方,例如Alchemy、nftscan、chainbase 等第三方链上API又存在速率和使用场景的限制,无法满足后台业务逻辑的使用。因此,搭建一套切合内部系统使用的NFT数据中台变得尤为重要。同时,还能为各类系统提供定制化的NFT充值入账等业务场景。
后台框架选型
对于后台业务,我们都不喜欢重复造轮子,MySQL、redis、代码生成这些是必要的,因此,基础框架决定使用go-admin 框架
介绍
go-admin 是一个中后台应用框架,基于(gin, gorm, Casbin, Vue, Element UI, Arco Design, Ant Design)实现。go-admin 分为两个项目go-admin 和 go-admin-ui,从名称上不难看出 go-admin 是后端服务,go-admin-ui 是 view 端服务。go-admin 主要提供一套标准化结构,让开发程序是对整个后端更加清晰彻底,也逐渐形成了独有的一套流程。
go-admin的目的是为了让开发者更方便快捷的梳理需求,专注业务,减少重复代码的编写,节省时间,提升人效,缩短项目周期,提升软件的开发效率以及质量,以早日实现不用加班的目的而努力!
特性
-
开箱即用
-
遵循 RESTful API 设计规范
-
基于 GIN WEB API 框架,提供了丰富的中间件支持(用户认证、跨域、访问日志、追踪 ID 等)
-
基于 Casbin 的 RBAC 访问控制模型
-
JWT 认证
-
支持 Swagger 文档(基于 swaggo)
-
基于 GORM 的数据库存储,可扩展多种类型数据库
-
配置文件简单的模型映射,快速能够得到想要的配置
-
代码生成工具
-
表单构建工具
-
TODO: 单元测试
数据库设计
链信息表
我们系统需要支持ethereum、polygon等诸多EVM区块链,每个链都有其专属的chainId,除了方便我们系统内部识别,也方便外部使用。字段设计如下:
CREATE TABLE `chain_info` (
`id` bigint(20) NOT NULL COMMENT 'PK',
`chain_id` varchar(50) DEFAULT NULL COMMENT '链ID',
`chain_name` varchar(50) DEFAULT NULL COMMENT '链名称',
`chain_token_symbol` varchar(50) DEFAULT NULL COMMENT '链代币符号',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='链信息';
NFT项目合集表
每个NFT都应该由一个合集进行归纳,这里的合集是指合约层,可以理解一个合约即为一个合集。因此我们这样设计字段:
CREATE TABLE `nft_project` (
`id` varchar(32) NOT NULL COMMENT 'PK',
`chain_id` varchar(50) DEFAULT NULL COMMENT '链ID',
`project_name` varchar(50) DEFAULT NULL COMMENT '项目名称',
`contract_address` varchar(100) DEFAULT NULL COMMENT '合约地址',
`nft_count` int(6) DEFAULT NULL COMMENT '藏品数',
`nft_type` varchar(50) DEFAULT NULL COMMENT '协议类型(erc721,erc1155)',
`img_url` varchar(255) DEFAULT NULL COMMENT '封面图',
`ipfs_url` varchar(255) DEFAULT NULL COMMENT 'IPFS地址',
`status` tinyint(1) DEFAULT NULL COMMENT '状态(0初始化1待拉取2拉取中3已拉取4拉取失败)',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`remark` varchar(50) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
UNIQUE KEY `contract_addr_unq` (`contract_address`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='NFT项目';
NFT 明细item表
我们有对每个NFT的名称、编号、图片、属性等需求,因此每个NFT应该被设计成一个个独立的数据行,该表字段设计如下:
CREATE TABLE `project_nft_item` (
`id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'PK',
`chain_id` varchar(50) NOT NULL COMMENT '链id',
`project_id` varchar(32) NOT NULL COMMENT '项目ID',
`nft_name` varchar(50) DEFAULT NULL COMMENT 'NFT名字',
`contract_address` varchar(50) DEFAULT NULL COMMENT '合约地址',
`card_nft_name` varchar(100) DEFAULT NULL COMMENT '艺术品名称',
`art_type` tinyint(1) DEFAULT '1' COMMENT '艺术品类型',
`token_id` varchar(10) NOT NULL COMMENT 'tokenId',
`multifile_type` varchar(50) DEFAULT NULL COMMENT '文件格式video/mp4,3dmodel/glb,image',
`ipfs_url` varchar(255) DEFAULT NULL COMMENT 'ipfs链接',
`nft_img_url` varchar(255) DEFAULT NULL COMMENT '藏品oss地址',
`create_time_stamp` bigint(13) DEFAULT NULL COMMENT '13位时间戳',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`description` text COMMENT '作品简介 一句话描述',
`oss_url_compress` varchar(255) DEFAULT NULL COMMENT '作品卡图片地址-压缩图',
`sub_picture` varchar(255) DEFAULT NULL COMMENT '视频主图',
`multfile_compress` varchar(255) DEFAULT NULL COMMENT '视频压缩文件',
`ipfs_address` varchar(255) DEFAULT NULL COMMENT 'ipfs源文件存储地址',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`version` int(11) DEFAULT '0' COMMENT '版本号',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `contract_token_unq` (`contract_address`,`token_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='NFT表';
NFT属性信息表
这里的属性其实是无规则的json结构,原本mysql是无法支持动态字段的,只能使用其json的特性,考虑到未来可能抽离出去,这里暂时为这一个字段单独独立一张表出来,字段设计如下:
CREATE TABLE `project_nft_properties` (
`id` varchar(32) NOT NULL COMMENT 'Pk',
`nft_item_id` varchar(32) DEFAULT NULL COMMENT 'Nft id',
`project_id` varchar(32) DEFAULT NULL COMMENT '项目id',
`chain_id` varchar(50) DEFAULT NULL COMMENT '链id',
`contract_address` varchar(100) DEFAULT NULL COMMENT '合约地址',
`token_id` varchar(10) DEFAULT NULL COMMENT 'nft编号',
`nft_properties` text COMMENT '属性',
PRIMARY KEY (`id`),
UNIQUE KEY `nft_id_unq` (`nft_item_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='nft属性信息';
NFT_IPFS解析记录表
NFT仍有大部分数据存于IPFS文件中,例如图片和属性信息,IPFS得从第三方API数据提供方获取,图片也需要从IPFS图片存储方下载并存到我们自己的OSS系统中,方便利用oss进行全球加速,因此我们需要设计一个IPFS解析记录表,方便从任意位置都可开始进行数据解析(第三方会限制IP和请求速率,因此这一步尤为重要)
CREATE TABLE `nft_ipfs_record` (
`id` varchar(32) NOT NULL COMMENT 'pk',
`nft_id` varchar(32) DEFAULT NULL COMMENT '藏品ID',
`chain_id` varchar(50) DEFAULT NULL COMMENT '链ID',
`contract_address` varchar(100) DEFAULT NULL COMMENT '合约地址',
`token_id` varchar(10) DEFAULT NULL COMMENT '藏品编号',
`ipfs_url` varchar(255) DEFAULT NULL COMMENT 'ipfs地址',
`img_url` varchar(255) DEFAULT NULL COMMENT '第三方图片地址',
`oss_url` varchar(255) DEFAULT NULL COMMENT 'oss地址',
`status` int(1) DEFAULT NULL COMMENT '状态0待处理1处理中2成功3失败',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`nft_properties` text COMMENT '属性JSON',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='NFT_IPFS解析记录';
区块扫描配置表
为了满足入账要求,需要对区块交易进行监听,因此对每个区块链进行扫描配置以便业务系统使用,字段设计如下:
CREATE TABLE `block_scan_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'PK',
`chain_id` varchar(50) DEFAULT NULL COMMENT '链编号',
`block_height` bigint(20) DEFAULT NULL COMMENT '区块高度',
`step_num` int(5) DEFAULT NULL COMMENT '每次查询步数',
`delay_block_num` int(5) DEFAULT NULL COMMENT '延迟区块数',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`status` int(1) DEFAULT NULL COMMENT '状态0禁用1启用',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='区块扫描配置';
监听配置信息表
用于监听指定交易信息,节省API对第三方节点的调用频率。字段设计如下:
CREATE TABLE `watch_config_info` (
`id` varchar(32) NOT NULL COMMENT 'pk',
`chain_id` varchar(50) NOT NULL COMMENT '链id',
`contract_address` varchar(100) DEFAULT NULL COMMENT '合约地址',
`address` varchar(100) DEFAULT NULL COMMENT '地址',
`status` int(1) DEFAULT '1' COMMENT '状态0无效1有效',
`notify_url` varchar(255) DEFAULT NULL COMMENT '回调地址',
PRIMARY KEY (`id`),
UNIQUE KEY `address_unq` (`chain_id`,`contract_address`,`address`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='监听配置信息';
监听入账交易记录表
把监听到的每一条交易信息存储和解析,用于回调订阅方系统以及满足内部系统查询使用。字段设计如下:
CREATE TABLE `watch_entry_record` (
`id` varchar(32) NOT NULL COMMENT 'Pk',
`chain_id` varchar(50) NOT NULL COMMENT '链编号',
`contract_address` varchar(100) DEFAULT NULL COMMENT '合约地址',
`token_id` varchar(10) DEFAULT NULL COMMENT '藏品编号',
`address` varchar(100) NOT NULL COMMENT '地址',
`hash` varchar(100) DEFAULT NULL COMMENT '交易hash',
`block_height` bigint(20) DEFAULT NULL COMMENT '区块高度',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_time_stamp` bigint(13) DEFAULT NULL COMMENT '创建时间戳',
`notify_url` varchar(255) DEFAULT NULL COMMENT '回调通知URL',
`notify_times` int(3) DEFAULT '0' COMMENT '回调次数',
`next_notify_time` datetime DEFAULT NULL COMMENT '下次回调时间',
`notify_status` int(1) DEFAULT '0' COMMENT '0待通知1通知中2已通知3通知失败',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='监听入账记录';
交易扫描记录表
这是一张中间表,用于追踪每笔hash的解析状态,因为第三方极有可能限制导致某笔交易无法解析,但是我们不能某笔交易解析失败而暂停区块扫描,区块更新速度也很快,因此这里记录解析状态。
CREATE TABLE `hash_scan_record` (
`id` varchar(32) NOT NULL COMMENT 'PK',
`chain_id` varchar(50) DEFAULT NULL COMMENT '链ID',
`hash` varchar(100) DEFAULT NULL COMMENT '交易hash',
`status` int(1) DEFAULT NULL COMMENT '状态1处理中2处理完成3处理失败',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='扫描交易记录';
Nft交易记录表
用于以结构化的方式记录NFT的交易记录,方便内部系统查询使用,字段设计如下:
CREATE TABLE `nft_trans_record` (
`id` varchar(32) NOT NULL COMMENT 'Pk',
`chain_id` varchar(50) NOT NULL COMMENT '链编号',
`contract_address` varchar(100) NOT NULL COMMENT '合约地址',
`token_id` varchar(10) NOT NULL COMMENT '藏品编号',
`from_address` varchar(100) NOT NULL COMMENT '发送方地址',
`to_address` varchar(100) NOT NULL COMMENT '接收人地址',
`hash` varchar(100) NOT NULL COMMENT 'hash',
`block_height` bigint(20) DEFAULT NULL COMMENT '区块高度',
`create_time` datetime DEFAULT NULL COMMENT '记录创建时间',
`trans_data` text COMMENT '交易数据',
`trans_method` varchar(255) DEFAULT NULL COMMENT '交易方法',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Nft交易记录';