手把手教你区块链java开发智能合约nft-第五篇(铸造第一个NFT)

Posted 悬弧

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手把手教你区块链java开发智能合约nft-第五篇(铸造第一个NFT)相关的知识,希望对你有一定的参考价值。

文章目录

手把手教你区块链java开发智能合约nft-第五篇(铸造第一个NFT)

回顾

初学区块链,那真叫一个痛苦并无助。如果没有人带你的话

今天写的这篇是在前面文章基础上写的,初学区块链的朋友建议先看我前面写的文章
手把手教你区块链java开发智能合约nft-第一篇
手把手教你区块链java开发智能合约nft-第二篇(部署第一个NFT智能合约)
手把手教你区块链java开发智能合约nft token-第三篇(部署token)
手把手教你区块链java开发智能合约nft(第四篇)-如何动态获取gasPrice和gasLimit?

部署NFT721

关于部署NFT721 ,可以参考之前的文章:
手把手教你区块链java开发智能合约nft-第二篇(部署第一个NFT智能合约)

部署完成后,将得到一个NFT721的智能合约地址:contractAddress,这个智能合约地址值需要保存好,待会铸造NFT时需要用到它

比如我在部署合约完成后,得到的contractAddress值为:0x1fc51bf18b49d29f7a40825914e8c68f4ce7b255

铸造NFT

铸造NFT也是比较简单的,直接调用NFT721 的方法mint 就可以了,主要难点是在对数据的签名上
直接上代码吧

 @Test
    public void mint() throws Exception 
        //NFT721合约地址
        String contractAddress="0x1fc51bf18b49d29f7a40825914e8c68f4ce7b255";
        String tokenId="2";   //上链的NFT id
        String tokenURI="/static/uploadQmVJoMsgcsCCz75ZHzup7e8boqhBz9R8SKYwKknFEWamzA.png";   //上链的tokenId对应的值
        //铸造NFT需要用到的私钥,在部署合约时指定的地址对应的私钥
        String miner="0x5369576889297382912123166219811286283737728368986117127236719812";

        TransactionManager transactionManager = getRawTransactionManager();
        ContractGasProvider contractGasProvider = getContractGasProvider();
        NFT721 nft721 = NFT721.load(contractAddress, web3j, transactionManager, contractGasProvider);
        Credentials credentials = getCredentials();

        ECKeyPair ecKeyPair = ECKeyPair.create(Numeric.hexStringToByteArray(miner));

        Type<BigInteger> tId = new Uint(new BigInteger(tokenId));
        String a = contractAddress + Numeric.cleanHexPrefix(TypeEncoder.encode(tId));
        a = Hash.sha3(a);
        byte[] b = Numeric.hexStringToByteArray(a);
        Sign.SignatureData data = Sign.signPrefixedMessage(b, ecKeyPair);


        ArrayList<NFT721.Fee> fees = Lists.newArrayList(new NFT721.Fee(credentials.getAddress(), BigInteger.valueOf(200)));
        TransactionReceipt transactionReceipt = nft721.mint(new BigInteger(tokenId), new BigInteger(data.getV()), data.getR(), data.getS(),
                fees, tokenURI).send();
        System.out.println("mint:hash::"+transactionReceipt.getTransactionHash());
        System.out.println("mint:getContractAddress::"+transactionReceipt.getContractAddress());
    

关键代码说明:

  • 首先定义了一些传入的参数,这里当做局部变量定义出来
  • 加载智能合约NFT721对象,要用这个对象来调用mint铸造NFT
     NFT721 nft721 = NFT721.load(contractAddress, web3j, transactionManager, contractGasProvider);
  • 对上链数据进行签名
//利用签名账户对应的私钥对上链的tokenId等数据进行签名
 ECKeyPair ecKeyPair = ECKeyPair.create(Numeric.hexStringToByteArray(miner));

        Type<BigInteger> tId = new Uint(new BigInteger(tokenId));
        String a = contractAddress + Numeric.cleanHexPrefix(TypeEncoder.encode(tId));
        a = Hash.sha3(a);
        byte[] b = Numeric.hexStringToByteArray(a);
        Sign.SignatureData data = Sign.signPrefixedMessage(b, ecKeyPair);
  • 铸造NFT
        ArrayList<NFT721.Fee> fees = Lists.newArrayList(new NFT721.Fee(credentials.getAddress(), BigInteger.valueOf(200)));
        TransactionReceipt transactionReceipt = nft721.mint(new BigInteger(tokenId), new BigInteger(data.getV()), data.getR(), data.getS(),
                fees, tokenURI).send();

mint方法参数说明:
public RemoteFunctionCall mint(BigInteger tokenId, BigInteger v, byte[] r, byte[] s, List _fees, String tokenURI)

tokenId:上链的tokenId,或者可以理解为NFT的id,必须保证在链上唯一
v: 签名数据的v
r:签名数据的R
s:签名数据的S
_fees: (我也不太理解具体是什么)从字面上理解是费用信息,

Fee构造方法需要传入两个参数:
public Fee(String recipient, BigInteger value)
super(new Address(recipient),
new Uint256(value));
this.recipient = recipient;
this.value = value;

从命名上看:
recipient : 接受者
value:费用

tokenURI:tokenURI,具体上链的数据,上链后可以通过tokenId查看的数据,一个tokenId需要指定一个tokenURI

执行完以上代码,没有报错的话,等一会就会铸造成功了
这样就完成了NFT的铸造了

根据tokenId查看NFT链上数据

    @Test
    public void tokenURI() throws Exception 

        String contractAddress="0x1fc51bf18b49d29f7a40825914e8c68f4ce7b255";
        String tokenId="2";
        TransactionManager transactionManager = getRawTransactionManager();
        ContractGasProvider contractGasProvider = getContractGasProvider();
        NFT721 nft721 = NFT721.load(contractAddress, web3j, transactionManager, contractGasProvider);
        String tokenURI = nft721.tokenURI(new BigInteger(tokenId)).send();
        System.out.println("tokenURI::"+tokenURI);
    

完整代码

package net.sandboxol.support.deploy.mint;

import net.sandboxol.support.deploy.NFT721;
import net.sandboxol.support.utils.Web3Util;
import org.assertj.core.util.Lists;
import org.junit.Test;
import org.web3j.abi.TypeEncoder;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.Uint;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.ECKeyPair;
import org.web3j.crypto.Hash;
import org.web3j.crypto.Sign;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.RawTransactionManager;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.tx.gas.StaticGasProvider;
import org.web3j.utils.Numeric;

import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;

public class DeployMintTest 
    Web3j web3j = Web3j.build(new HttpService("http://192.168.159.101:8545/"));
	private String userId="214158";
    private String siteId="ishow";
    @Test
    public void mint() throws Exception 

        String contractAddress="0x1fc51bf18b49d29f7a40825914e8c68f4ce7b255";
        String tokenId="2";
        String tokenURI="/static/uploadQmVJoMsgcsCCz75ZHzup7e8boqhBz9R8SKYwKknFEWamzA.png";
        //私钥
        String miner="0x5369576889297382912123166219811286283737728368986117127236719812";

        TransactionManager transactionManager = getRawTransactionManager();
        ContractGasProvider contractGasProvider = getContractGasProvider();
        NFT721 nft721 = NFT721.load(contractAddress, web3j, transactionManager, contractGasProvider);
        Credentials credentials = getCredentials();

        ECKeyPair ecKeyPair = ECKeyPair.create(Numeric.hexStringToByteArray(miner));



        Type<BigInteger> tId = new Uint(new BigInteger(tokenId));
        String a = contractAddress + Numeric.cleanHexPrefix(TypeEncoder.encode(tId));
        a = Hash.sha3(a);
        byte[] b = Numeric.hexStringToByteArray(a);
        Sign.SignatureData data = Sign.signPrefixedMessage(b, ecKeyPair);


        ArrayList<NFT721.Fee> fees = Lists.newArrayList(new NFT721.Fee(credentials.getAddress(), BigInteger.valueOf(200)));
        TransactionReceipt transactionReceipt = nft721.mint(new BigInteger(tokenId), new BigInteger(data.getV()), data.getR(), data.getS(),
                fees, tokenURI).send();
        System.out.println("mint:hash::"+transactionReceipt.getTransactionHash());
        System.out.println("mint:getContractAddress::"+transactionReceipt.getContractAddress());
    


    @Test
    public void tokenURI() throws Exception 

        String contractAddress="0x1fc51bf18b49d29f7a40825914e8c68f4ce7b255";
        String tokenId="1";
        TransactionManager transactionManager = getRawTransactionManager();
        ContractGasProvider contractGasProvider = getContractGasProvider();
        NFT721 nft721 = NFT721.load(contractAddress, web3j, transactionManager, contractGasProvider);
        String tokenURI = nft721.tokenURI(new BigInteger(tokenId)).send();
        System.out.println("tokenURI::"+tokenURI);
    

    private Credentials getCredentials () 
    //这个Web3Util 是自己定义的工具,能根据userId和siteId生成Credentials 对象的工具,大家可以自己构造,我这个有其他依赖,不方便提供源码
        return Web3Util.getUserCredentials(userId,siteId);
    

    private TransactionManager getRawTransactionManager() throws IOException 
        BigInteger chainId = web3j.ethChainId().send().getChainId();
        return new RawTransactionManager(web3j, getCredentials(),chainId.longValue());
    

    private ContractGasProvider getContractGasProvider()
        return new StaticGasProvider(BigInteger.valueOf(22_000_000_000l),BigInteger.valueOf(6_700_000l));
    

NFT721 相关智能合约源码下载

手把手教你区块链java开发智能合约nft-第一篇

文章目录

手把手教你区块链java开发智能合约nft-第一篇

刚接触区块链开发,使用java开发,真的是太难了,自己一步步摸索,从新手小白一路碰壁,动不动就报错,去网上搜索对应错误,还真什么都搜索不到,摸索了三四个月,今天终于有了一些进展,今天开始分享出来,希望能帮助到需要的朋友

我作为一个java后端的程序员,不会写智能合约,但是可以找对应会的人写,或者自己网上找资料自己写。这里只介绍怎么将智能合约转为java代码

如何将智能合约转成java代码?
我了解的有好2两种方式,具体可以参考:

  1. 区块链智能合约转为java代码
  2. web3j 开源框架代码执行转java代码

我这里主要介绍第二种方式

安装基础环境

  1. nodejs
  2. truffle #编译智能合约要使用

基础环境安装不多介绍,具体点击查看安装 nodejstruffle

编写智能合约

  1. 创建文件夹
mkdir MetaCoin
cd MetaCoin
  1. 下载(“unbox”) MetaCoin box
truffle unbox metacoin

下载完成后,会看到几个文件夹
contracts/: Solidity contracts 目录,智能合约代码就在这里编写
migrations/: Directory for scriptable deployment files
test/: Directory for test files for testing your application and contracts 测试智能合约的目录,主要写测试用例
truffle.js: Truffle configuration file ,配置文件

  1. 编译智能合约
    自己编写完智能合约后,执行以下命令进行编译
truffle compile

编译完成后,会生成build目录,目录下会生成.json文件,这些json文件就是用来生成java代码的文件

使用web3j 开源框架生成java代码

  1. 下载源码
git clone https://github.com/web3j/web3j.git
  1. idea打开web3j

    idea打开后,会自动下载相关依赖包,下载完成,就可以运行相关的代码,生成java代码了

  2. 找到项目codegen
    找到项目并定位到具体类:org.web3j.codegen.TruffleJsonFunctionWrapperGenerator
    先运行一下main方法,之后在去配置运行参数

4.配置参数

  • 点击编辑配置
  • 配置参数

    参数格式如下:
org.web3j.codegen.TruffleJsonFunctionWrapperGenerator /path/to/<truffle-smart-contract-output>.json -o /path/to/src/main/java -p com.your.organisation.name

第一个参数:指定编译后的智能合约对应json串位置
第二个参数:-o 指定输入java代码的位置
第三个参数:生成java代码的位置
第四个参数:-p 指定生成java代码的包名
第五个参数:生成java代码的包名

配置完参数之后,点击OK确认保存

  1. 运行TruffleJsonFunctionWrapperGenerator ,就可以将智能合约生成java代码了

以上是关于手把手教你区块链java开发智能合约nft-第五篇(铸造第一个NFT)的主要内容,如果未能解决你的问题,请参考以下文章

区块链 | NFT手把手教你如何生成式NFT艺术品创作 详细教程

一学就会,手把手教你用Go语言调用智能合约

Flow区块链NFT开发及部署教程Cadence合约

BSV资讯感应合约大幅推进BSV区块链上的NFT和智能合约方案

10个最适合开发NFT的区块链

手把手教你发行代币