区块链NFT开发常见问题:Only read operations are supported by this transaction manager 解决

区块链NFT开发常见问题:Only read operations are supported by this transaction manager 解决

问题描述

区块链NFT开发操作上链时报错如下

java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException: Only read operations are supported by this transaction manager

	at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:396)
	at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2073)
	at net.sandbox.gpt.webapi.Web3Test.chkApprovedForAll(Web3Test.java:170)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
	at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.UnsupportedOperationException: Only read operations are supported by this transaction manager
	at org.web3j.tx.ReadonlyTransactionManager.sendTransaction(ReadonlyTransactionManager.java:45)
	at org.web3j.tx.TransactionManager.executeTransaction(TransactionManager.java:81)
	at org.web3j.tx.ManagedTransaction.send(ManagedTransaction.java:128)
	at org.web3j.tx.Contract.executeTransaction(Contract.java:367)
	at org.web3j.tx.Contract.executeTransaction(Contract.java:350)
	at org.web3j.tx.Contract.executeTransaction(Contract.java:344)
	at org.web3j.tx.Contract.executeTransaction(Contract.java:339)
	at org.web3j.tx.Contract.lambda$executeRemoteCallTransaction$3(Contract.java:410)
	at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:42)
	at org.web3j.utils.Async.lambda$run$1(Async.java:38)
	at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)

关键代码如下

	public static Boolean setApprovedForAll(String token,String owner, String operator){
    
    
		TransactionManager transactionManager = new ReadonlyTransactionManager(web3j, token);
		ERC721 contract721 = ERC721.load(token, web3j, transactionManager, new DefaultGasProvider());
		try {
    
    
			TransactionReceipt tr = contract721.setApprovalForAll(operator,true).sendAsync().get();
			if(tr.getBlockHash().isEmpty()) return false;
		} catch (InterruptedException | ExecutionException e) {
    
    
			logger.error("获取721uri异常", e);
			return null;
		}
		return true;
	}

执行到contract721.setApprovalForAll(operator,true).sendAsync().get(); 方法调用时就报了问题的错误

问题分析

报错原因是因为操作了事务,而传入合约的事务管理却是只读的实例ReadonlyTransactionManager,只读事务管理是不支持操作的,因此会报问题所列错误,其实除了我这个案例之外,其他任何上链操作时,传入的事务也不能是只读事务,否则都会报我这种错误

问题解决

将只读事务管理参数修改为RawTransactionManager 实例就好,参考代码如下:

        TransactionManager transactionManager = new RawTransactionManager(web3j, getCredentials(),web3j.ethChainId().send().getChainId().longValue());
//        TransactionManager transactionManager = new ReadonlyTransactionManager(web3j,token);
        ERC721 contract721 = ERC721.load(token, web3j, transactionManager, new DefaultGasProvider());;

猜你喜欢

转载自blog.csdn.net/huangxuanheng/article/details/125333548