From 2ceb1fadaa138c95a6d62cc482909534fc9da203 Mon Sep 17 00:00:00 2001
From: kyonRay <rui.kwok@outlook.com>
Date: Tue, 5 Dec 2023 20:28:37 +0800
Subject: [PATCH] <feat>(transaction): impl AssembleTransactionService, add
 integration test of it.

---
 .../decoder/HashCalculatorTest.java           |   3 +
 .../manager/TransactionManagerTest.java       | 707 ++++++++++++++++++
 .../bcos/sdk/v3/codec/ContractCodec.java      |   6 +
 .../fisco/bcos/sdk/v3/codec/abi/Constant.java |   2 +-
 .../AssembleEIP1559TransactionService.java    | 175 +++++
 .../AssembleTransactionService.java           | 448 ++++++-----
 .../DefaultTransactionManager.java            |  20 +-
 .../ProxySignTransactionManager.java          |  16 +-
 .../Transactionv2/TransactionManager.java     |   8 +
 .../dto/DeployTransactionRequest.java         |  48 ++
 ...loyTransactionRequestWithStringParams.java |  43 ++
 .../Transactionv2/dto/TransactionRequest.java |  98 +++
 .../TransactionRequestWithStringParams.java   |  44 ++
 .../utils/TransactionRequestBuilder.java      | 150 ++++
 .../org/fisco/bcos/sdk/v3/utils/Numeric.java  |   3 +
 15 files changed, 1547 insertions(+), 224 deletions(-)
 create mode 100644 src/integration-test/java/org/fisco/bcos/sdk/v3/test/transaction/manager/TransactionManagerTest.java
 create mode 100644 src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/AssembleEIP1559TransactionService.java
 create mode 100644 src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/DeployTransactionRequest.java
 create mode 100644 src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/DeployTransactionRequestWithStringParams.java
 create mode 100644 src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/TransactionRequest.java
 create mode 100644 src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/TransactionRequestWithStringParams.java
 create mode 100644 src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/utils/TransactionRequestBuilder.java

diff --git a/src/integration-test/java/org/fisco/bcos/sdk/v3/test/transaction/decoder/HashCalculatorTest.java b/src/integration-test/java/org/fisco/bcos/sdk/v3/test/transaction/decoder/HashCalculatorTest.java
index 8874c0b07..d6d91ad41 100644
--- a/src/integration-test/java/org/fisco/bcos/sdk/v3/test/transaction/decoder/HashCalculatorTest.java
+++ b/src/integration-test/java/org/fisco/bcos/sdk/v3/test/transaction/decoder/HashCalculatorTest.java
@@ -149,6 +149,9 @@ public void testTxProof() {
         if (transactionResponse == null && block.getNumber() == 0) {
             return;
         }
+        if (client.getChainCompatibilityVersion().compareTo(EnumNodeVersion.BCOS_3_2_0.toVersionObj()) < 0) {
+            return;
+        }
         if (client.getCryptoSuite().cryptoTypeConfig == CryptoType.ECDSA_TYPE) {
             boolean verifyMerkle = MerkleProofUtility.verifyMerkle(block.getTransactionsRoot(), transactionResponse.getTxProof(), transactionResponse.getHash(), new Keccak256());
             Assert.assertTrue(verifyMerkle);
diff --git a/src/integration-test/java/org/fisco/bcos/sdk/v3/test/transaction/manager/TransactionManagerTest.java b/src/integration-test/java/org/fisco/bcos/sdk/v3/test/transaction/manager/TransactionManagerTest.java
new file mode 100644
index 000000000..069713383
--- /dev/null
+++ b/src/integration-test/java/org/fisco/bcos/sdk/v3/test/transaction/manager/TransactionManagerTest.java
@@ -0,0 +1,707 @@
+package org.fisco.bcos.sdk.v3.test.transaction.manager;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.fisco.bcos.sdk.v3.BcosSDK;
+import org.fisco.bcos.sdk.v3.client.Client;
+import org.fisco.bcos.sdk.v3.codec.datatypes.Bytes;
+import org.fisco.bcos.sdk.v3.codec.datatypes.DynamicArray;
+import org.fisco.bcos.sdk.v3.codec.datatypes.DynamicBytes;
+import org.fisco.bcos.sdk.v3.codec.datatypes.DynamicStruct;
+import org.fisco.bcos.sdk.v3.codec.datatypes.StaticArray;
+import org.fisco.bcos.sdk.v3.codec.datatypes.StaticStruct;
+import org.fisco.bcos.sdk.v3.codec.datatypes.Type;
+import org.fisco.bcos.sdk.v3.codec.datatypes.Utf8String;
+import org.fisco.bcos.sdk.v3.codec.datatypes.generated.Bytes32;
+import org.fisco.bcos.sdk.v3.codec.datatypes.generated.Int128;
+import org.fisco.bcos.sdk.v3.codec.datatypes.generated.Int32;
+import org.fisco.bcos.sdk.v3.codec.datatypes.generated.Uint128;
+import org.fisco.bcos.sdk.v3.codec.wrapper.ABIObject;
+import org.fisco.bcos.sdk.v3.crypto.signature.SignatureResult;
+import org.fisco.bcos.sdk.v3.model.ConstantConfig;
+import org.fisco.bcos.sdk.v3.model.EnumNodeVersion;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.AssembleTransactionService;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.ProxySignTransactionManager;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.DeployTransactionRequest;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.DeployTransactionRequestWithStringParams;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.TransactionRequest;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.TransactionRequestWithStringParams;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.utils.TransactionRequestBuilder;
+import org.fisco.bcos.sdk.v3.transaction.model.dto.CallResponse;
+import org.fisco.bcos.sdk.v3.transaction.model.dto.TransactionResponse;
+import org.fisco.bcos.sdk.v3.transaction.signer.AsyncTransactionSignercInterface;
+import org.fisco.bcos.sdk.v3.transaction.signer.RemoteSignCallbackInterface;
+import org.fisco.bcos.sdk.v3.transaction.tools.ContractLoader;
+import org.fisco.bcos.sdk.v3.transaction.tools.JsonUtils;
+import org.fisco.bcos.sdk.v3.utils.Hex;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class)
+public class TransactionManagerTest {
+
+    @Parameterized.Parameter
+    public boolean useProxySign;
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> data() {
+        return Arrays.asList(
+                new Object[][]{
+                        {false},
+                        {true},
+                });
+    }
+
+    private static final String CONFIG_FILE =
+            "src/integration-test/resources/" + ConstantConfig.CONFIG_FILE_NAME;
+    private static final String ABI_FILE = "src/integration-test/resources/abi/";
+    private static final String BIN_FILE = "src/integration-test/resources/bin/";
+
+    private static final String COMPLEX_CODEC_TEST = "ComplexCodecTest";
+
+    private final AssembleTransactionService transactionService;
+
+    private final ContractLoader contractLoader;
+
+    private final Client client;
+
+    public TransactionManagerTest() throws IOException {
+        // init the sdk, and set the config options.
+        BcosSDK sdk = BcosSDK.build(CONFIG_FILE);
+        // group
+        client = sdk.getClient("group0");
+        transactionService = new AssembleTransactionService(client);
+        if (useProxySign) {
+            ProxySignTransactionManager proxySignTransactionManager = new ProxySignTransactionManager(client, (hash, transactionSignCallback) -> {
+                SignatureResult sign = client.getCryptoSuite().sign(hash, client.getCryptoSuite().getCryptoKeyPair());
+                transactionSignCallback.handleSignedTransaction(sign);
+            });
+            transactionService.setTransactionManager(proxySignTransactionManager);
+        }
+        contractLoader = new ContractLoader(ABI_FILE, BIN_FILE);
+    }
+
+    @Test
+    public void test1ComplexCodecWithType() throws Exception {
+        if (client.getChainCompatibilityVersion().compareTo(EnumNodeVersion.BCOS_3_6_0.toVersionObj()) < 0) {
+            return;
+        }
+        // test deploy with struct
+        List<Object> deployParams = new ArrayList<>();
+        {
+            DynamicArray<Utf8String> array = new DynamicArray<>(Utf8String.class, new Utf8String("test"));
+            DynamicArray<Bytes32> bytes32DynamicArray = new DynamicArray<>(Bytes32.class, Bytes32.DEFAULT);
+            DynamicStruct structA = new DynamicStruct(array, bytes32DynamicArray);
+            deployParams.add(structA);
+        }
+
+        Pair<String, String> abiAndBinaryByContractName = contractLoader.getABIAndBinaryByContractName(COMPLEX_CODEC_TEST);
+        String abi = abiAndBinaryByContractName.getKey();
+        TransactionRequestBuilder builder = new TransactionRequestBuilder(abi, abiAndBinaryByContractName.getValue());
+        DeployTransactionRequest request = builder.buildDeployRequest(deployParams);
+
+        TransactionResponse response = transactionService.deployContract(request);
+
+        Assert.assertEquals(response.getTransactionReceipt().getStatus(), 0);
+        String contractAddress = response.getContractAddress();
+        Assert.assertTrue(StringUtils.isNotBlank(response.getContractAddress()));
+
+        // test call get struct
+        {
+            TransactionRequest callRequest = builder.setTo(contractAddress).setMethod("getStructA").buildRequest(new ArrayList<>());
+            CallResponse callResponse = transactionService.sendCall(callRequest);
+
+            List<Object> returnObject = callResponse.getReturnObject();
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(callResponse.getReturnABIObject().size(), 1);
+            System.out.println(JsonUtils.toJson(returnObject));
+
+            List<Object> callParams = new ArrayList<>();
+            DynamicArray<Utf8String> array = new DynamicArray<>(Utf8String.class, new Utf8String("test3125643123"));
+            DynamicArray<Bytes32> bytes32DynamicArray = new DynamicArray<>(Bytes32.class, Bytes32.DEFAULT);
+            DynamicStruct structA = new DynamicStruct(array, bytes32DynamicArray);
+            callParams.add(structA);
+
+
+            TransactionRequest callRequest2 = builder.setMethod("getStructA").buildRequest(callParams);
+            CallResponse callResponse1 = transactionService.sendCall(callRequest2);
+
+            returnObject = callResponse1.getReturnObject();
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(callResponse1.getReturnABIObject().size(), 1);
+            System.out.println("getStructA:");
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test bytes[][] set and get
+        {
+            List<Object> params = new ArrayList<>();
+            DynamicBytes b = new DynamicBytes("1234".getBytes());
+            DynamicArray<DynamicBytes> bs = new DynamicArray<>(DynamicBytes.class, b);
+            DynamicArray<DynamicArray<DynamicBytes>> bbs = new DynamicArray<>(bs);
+            params.add(bbs);
+
+            TransactionRequest transactionRequest = builder.setMethod("setBytesArrayArray").buildRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransaction(transactionRequest);
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            Assert.assertEquals(Hex.toHexString(((DynamicBytes) ((DynamicArray<?>) ((DynamicArray<?>) results.get(0)).getValue().get(0)).getValue().get(0)).getValue()), Hex.toHexString("1234".getBytes()));
+            System.out.println("setBytesArrayArray, bytes[][]");
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test bytes32[][] set and get
+        {
+            List<Object> params = new ArrayList<>();
+            Bytes32 b = new Bytes32(Hex.decode("ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff"));
+            DynamicArray<Bytes32> bs = new DynamicArray<>(Bytes32.class, b);
+            DynamicArray<DynamicArray<Bytes32>> bbs = new DynamicArray<>(bs);
+            params.add(bbs);
+
+            TransactionRequest transactionRequest = builder.setMethod("setBytes32ArrayArray").buildRequest(params);
+
+            TransactionResponse transactionResponse = transactionService.sendTransaction(transactionRequest);
+
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            Assert.assertEquals(Hex.toHexString(((Bytes) ((DynamicArray<?>) ((DynamicArray<?>) results.get(0)).getValue().get(0)).getValue().get(0)).getValue()), "ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff");
+            System.out.println("setBytes32ArrayArray, bytes32[][]");
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test bytes[2][] set and get
+        {
+            List<Object> params = new ArrayList<>();
+            DynamicBytes b1 = new DynamicBytes(Hex.decode("ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff"));
+            DynamicBytes b2 = DynamicBytes.DEFAULT;
+            DynamicArray<DynamicBytes> bs = new DynamicArray<>(DynamicBytes.class, b1, b2);
+            DynamicArray<DynamicArray<DynamicBytes>> bbs = new DynamicArray<>(bs);
+            params.add(bbs);
+
+            TransactionRequest transactionRequest = builder.setMethod("setBytesStaticArrayArray").buildRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransaction(transactionRequest);
+
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            Assert.assertEquals(Hex.toHexString(((DynamicBytes) ((DynamicArray<?>) ((DynamicArray<?>) results.get(0)).getValue().get(0)).getValue().get(0)).getValue()), "ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff");
+            System.out.println("setBytesStaticArrayArray, bytes[2][]");
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test bytes32[2][] set and get
+        {
+            List<Object> params = new ArrayList<>();
+            Bytes32 b1 = new Bytes32(Hex.decode("ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff"));
+            Bytes32 b2 = Bytes32.DEFAULT;
+            StaticArray<Bytes32> bs = new StaticArray<>(Bytes32.class, b1, b2);
+            DynamicArray<StaticArray<Bytes32>> bbs = new DynamicArray<>(bs);
+            params.add(bbs);
+
+            TransactionRequest transactionRequest = builder.setMethod("setBytes32StaticArrayArray").buildRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransaction(transactionRequest);
+
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            Assert.assertEquals(Hex.toHexString(((Bytes) ((StaticArray<?>) ((DynamicArray<?>) results.get(0)).getValue().get(0)).getValue().get(0)).getValue()), "ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff");
+            System.out.println("setBytes32StaticArrayArray, bytes32[2][]");
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test struct set and get
+        {
+            List<Object> params = new ArrayList<>();
+            DynamicArray<Utf8String> array = new DynamicArray<>(Utf8String.class, new Utf8String("test2132131"));
+            DynamicArray<Bytes32> bytes32DynamicArray = new DynamicArray<>(Bytes32.class, Bytes32.DEFAULT);
+            DynamicStruct structA = new DynamicStruct(array, bytes32DynamicArray);
+            params.add(structA);
+
+            TransactionRequest transactionRequest = builder.setMethod("buildStructB").buildRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransaction(transactionRequest);
+
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 2);
+            Assert.assertEquals(returnObject.size(), 2);
+            Assert.assertEquals(returnABIObject.size(), 2);
+            System.out.println("buildStructB, StructB, StructA[]");
+            System.out.println(JsonUtils.toJsonWithException(returnObject));
+        }
+
+        // test static struct set and get
+        {
+            List<Object> params = new ArrayList<>();
+            StaticArray<Int32> staticArray = new StaticArray<>(Int32.class, 1, new Int32(1));
+            Int128 int128 = new Int128(128);
+            Uint128 uint128 = new Uint128(127);
+            StaticStruct struct = new StaticStruct(int128, uint128, staticArray);
+            params.add(struct);
+
+            // use static struct params, get single struct
+            TransactionRequest transactionRequest = builder.setMethod("buildStaticStruct").buildRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransaction(transactionRequest);
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            System.out.println("buildStaticStruct, staticStruct");
+            System.out.println(JsonUtils.toJsonWithException(returnObject));
+
+            // use number params, get static struct list
+            List<Object> params2 = new ArrayList<>();
+            params2.add(new Int128(256));
+            params2.add(new Uint128(288));
+            TransactionRequest transactionRequest1 = builder.setMethod("buildStaticStruct").buildRequest(params2);
+            TransactionResponse transactionResponse1 = transactionService.sendTransaction(transactionRequest1);
+            Assert.assertEquals(transactionResponse1.getTransactionReceipt().getStatus(), 0);
+            results = transactionResponse1.getResults();
+            returnObject = transactionResponse1.getReturnObject();
+            returnABIObject = transactionResponse1.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            System.out.println("buildStaticStruct, staticStruct[]");
+            System.out.println(JsonUtils.toJsonWithException(returnObject));
+        }
+    }
+
+    @Test
+    public void test2ComplexCodecWithStringParams() throws Exception {
+        if (client.getChainCompatibilityVersion().compareTo(EnumNodeVersion.BCOS_3_6_0.toVersionObj()) < 0) {
+            return;
+        }
+        // test deploy with struct
+        List<String> deployParams = new ArrayList<>();
+
+        deployParams.add("[[\"test\"],[\"ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff\"]]");
+        Pair<String, String> abiAndBinaryByContractName = contractLoader.getABIAndBinaryByContractName(COMPLEX_CODEC_TEST);
+        String abi = abiAndBinaryByContractName.getKey();
+        TransactionRequestBuilder requestBuilder = new TransactionRequestBuilder(abi, abiAndBinaryByContractName.getValue());
+        DeployTransactionRequestWithStringParams deployTransactionRequestWithStringParams = requestBuilder.buildDeployStringParamsRequest(deployParams);
+        TransactionResponse response = transactionService.deployContractWithStringParams(deployTransactionRequestWithStringParams);
+        Assert.assertEquals(response.getTransactionReceipt().getStatus(), 0);
+        String contractAddress = response.getContractAddress();
+        Assert.assertTrue(StringUtils.isNotBlank(response.getContractAddress()));
+
+        // test call send struct get struct
+        {
+            List<String> callParams = new ArrayList<>();
+            // use no params method
+            TransactionRequestWithStringParams request = requestBuilder.setMethod("getStructA").setTo(contractAddress).buildStringParamsRequest(callParams);
+            CallResponse callResponse = transactionService.sendCallWithStringParams(request);
+            List<Object> returnObject = callResponse.getReturnObject();
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(callResponse.getReturnABIObject().size(), 1);
+            System.out.println(JsonUtils.toJson(returnObject));
+
+            // use one params method
+            callParams.add("[[\"test2312312312312\"],[\"ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff\"]]");
+            TransactionRequestWithStringParams request2 = requestBuilder.setMethod("getStructA").setTo(contractAddress).buildStringParamsRequest(callParams);
+            CallResponse callResponse2 = transactionService.sendCallWithStringParams(request2);
+            returnObject = callResponse2.getReturnObject();
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(callResponse2.getReturnABIObject().size(), 1);
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test bytes[][] set and get
+        {
+            List<String> params = new ArrayList<>();
+            params.add("[[\"0xabcd\"],[\"0x1234\"]]");
+            TransactionRequestWithStringParams transactionRequestWithStringParams = requestBuilder.setMethod("setBytesArrayArray").setTo(contractAddress).buildStringParamsRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransactionWithStringParams(transactionRequestWithStringParams);
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            Assert.assertEquals(Hex.toHexString(((DynamicBytes) ((DynamicArray<?>) ((DynamicArray<?>) results.get(0)).getValue().get(0)).getValue().get(0)).getValue()), "abcd");
+        }
+
+        // test bytes32[][] set and get
+        {
+            List<String> params = new ArrayList<>();
+            params.add("[[\"0xffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff\",\"0xffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff\"],[\"0xffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff\"]]");
+            TransactionRequestWithStringParams transactionRequestWithStringParams = requestBuilder.setMethod("setBytes32ArrayArray").buildStringParamsRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransactionWithStringParams(transactionRequestWithStringParams);
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            Assert.assertEquals(Hex.toHexString(((Bytes) ((DynamicArray<?>) ((DynamicArray<?>) results.get(0)).getValue().get(0)).getValue().get(0)).getValue()), "ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff");
+            System.out.println("setBytes32ArrayArray, bytes32[][]");
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test bytes[2][] set and get
+        {
+            List<String> params = new ArrayList<>();
+            params.add("[[\"0xabcdef\",\"0xffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff\"],[\"0xffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff\",\"0x1234\"]]");
+            TransactionRequestWithStringParams transactionRequestWithStringParams = requestBuilder.setMethod("setBytesStaticArrayArray").buildStringParamsRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransactionWithStringParams(transactionRequestWithStringParams);
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            Assert.assertEquals(Hex.toHexString(((DynamicBytes) ((DynamicArray<?>) ((DynamicArray<?>) results.get(0)).getValue().get(0)).getValue().get(0)).getValue()), "abcdef");
+            System.out.println("setBytesStaticArrayArray, bytes[2][]");
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test bytes32[2][] set and get
+        {
+            List<String> params = new ArrayList<>();
+            params.add("[[\"0x1234567890123456789012345678901234567890123456789012345678901234\",\"0xffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff\"],[\"0x1234567890123456789012345678901234567890123456789012345678901234\",\"0xffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff\"],[\"0xffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff\",\"0x1234567890123456789012345678901234567890123456789012345678901234\"]]");
+            TransactionRequestWithStringParams transactionRequestWithStringParams = requestBuilder.setMethod("setBytes32StaticArrayArray").buildStringParamsRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransactionWithStringParams(transactionRequestWithStringParams);
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            Assert.assertEquals(Hex.toHexString(((Bytes) ((StaticArray<?>) ((DynamicArray<?>) results.get(0)).getValue().get(0)).getValue().get(0)).getValue()), "1234567890123456789012345678901234567890123456789012345678901234");
+            System.out.println("setBytes32StaticArrayArray, bytes32[2][]");
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test struct set and get
+        {
+            List<String> params = new ArrayList<>();
+            params.add("[[\"12312314565456345test\"],[\"ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff\"]]");
+            TransactionRequestWithStringParams transactionRequestWithStringParams = requestBuilder.setMethod("buildStructB").buildStringParamsRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransactionWithStringParams(transactionRequestWithStringParams);
+
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 2);
+            Assert.assertEquals(returnObject.size(), 2);
+            Assert.assertEquals(returnABIObject.size(), 2);
+            System.out.println("buildStructB, StructB, StructA[]");
+            System.out.println(JsonUtils.toJsonWithException(returnObject));
+        }
+
+        // test static struct set and get
+        {
+            List<String> params = new ArrayList<>();
+            params.add("[-128,129,[32]]");
+            // use static struct params, get single struct
+            TransactionRequestWithStringParams transactionRequestWithStringParams = requestBuilder.setMethod("buildStaticStruct").buildStringParamsRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransactionWithStringParams(transactionRequestWithStringParams);
+
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            System.out.println("buildStaticStruct, staticStruct");
+            System.out.println(JsonUtils.toJsonWithException(returnObject));
+            // use number params, get static struct list
+
+            List<String> params2 = new ArrayList<>();
+            params2.add("-256");
+            params2.add("12321421");
+            TransactionRequestWithStringParams transactionRequestWithStringParams2 = requestBuilder.setMethod("buildStaticStruct").buildStringParamsRequest(params2);
+            TransactionResponse transactionResponse2 = transactionService.sendTransactionWithStringParams(transactionRequestWithStringParams2);
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            results = transactionResponse2.getResults();
+            returnObject = transactionResponse2.getReturnObject();
+            returnABIObject = transactionResponse2.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            System.out.println("buildStaticStruct, staticStruct[]");
+            System.out.println(JsonUtils.toJsonWithException(returnObject));
+
+        }
+    }
+
+    @Test
+    public void test1ComplexCodecWithJavaObject() throws Exception {
+        if (client.getChainCompatibilityVersion().compareTo(EnumNodeVersion.BCOS_3_6_0.toVersionObj()) < 0) {
+            return;
+        }
+        // test deploy with struct
+        List<Object> deployParams = new ArrayList<>();
+        {
+            //    struct StructA {
+            //        string[] value_str;
+            //        bytes32[] bytes32_in_struct;
+            //    }
+            List<String> array = new ArrayList<>();
+            array.add("test");
+            List<byte[]> bytes = new ArrayList<>();
+            byte[] b = Bytes32.DEFAULT.getValue();
+            bytes.add(b);
+            List<Object> structA = new ArrayList<>();
+            structA.add(array);
+            structA.add(bytes);
+            deployParams.add(structA);
+        }
+        Pair<String, String> abiAndBinaryByContractName = contractLoader.getABIAndBinaryByContractName(COMPLEX_CODEC_TEST);
+        String abi = abiAndBinaryByContractName.getKey();
+        TransactionRequestBuilder requestBuilder = new TransactionRequestBuilder(abi, abiAndBinaryByContractName.getValue());
+        DeployTransactionRequest request = requestBuilder.buildDeployRequest(deployParams);
+
+        TransactionResponse response = transactionService.deployContract(request);
+
+        Assert.assertEquals(response.getTransactionReceipt().getStatus(), 0);
+        String contractAddress = response.getContractAddress();
+        Assert.assertTrue(StringUtils.isNotBlank(response.getContractAddress()));
+
+        // test call get struct
+        {
+            TransactionRequest transactionRequest = requestBuilder.setTo(contractAddress).setMethod("getStructA").buildRequest(new ArrayList<>());
+            // not params method
+            CallResponse callResponse = transactionService.sendCall(transactionRequest);
+            List<Object> returnObject = callResponse.getReturnObject();
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(callResponse.getReturnABIObject().size(), 1);
+            System.out.println(JsonUtils.toJson(returnObject));
+
+            //    struct StructA {
+            //        string[] value_str;
+            //        bytes32[] bytes32_in_struct;
+            //    }
+            List<Object> callParams = new ArrayList<>();
+            List<String> array = new ArrayList<>();
+            array.add("test31241233123");
+            List<byte[]> bytes = new ArrayList<>();
+            byte[] b = Bytes32.DEFAULT.getValue();
+            byte[] b2 = Bytes32.DEFAULT.getValue();
+            bytes.add(b);
+            bytes.add(b2);
+            List<Object> structA = new ArrayList<>();
+            structA.add(array);
+            structA.add(bytes);
+            callParams.add(structA);
+
+            TransactionRequest transactionRequest2 = requestBuilder.setMethod("getStructA").buildRequest(callParams);
+            CallResponse callResponse2 = transactionService.sendCall(transactionRequest2);
+
+            returnObject = callResponse2.getReturnObject();
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(callResponse2.getReturnABIObject().size(), 1);
+            System.out.println("getStructA:");
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test bytes[][] set and get
+        {
+            List<Object> params = new ArrayList<>();
+            byte[] b = "1234".getBytes();
+            List<byte[]> bs = new ArrayList<>();
+            bs.add(b);
+            List<List<byte[]>> bss = new ArrayList<>();
+            bss.add(bs);
+            params.add(bss);
+
+            TransactionRequest transactionRequest = requestBuilder.setMethod("setBytesArrayArray").buildRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransaction(transactionRequest);
+
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            Assert.assertEquals(Hex.toHexString(((DynamicBytes) ((DynamicArray<?>) ((DynamicArray<?>) results.get(0)).getValue().get(0)).getValue().get(0)).getValue()), Hex.toHexString("1234".getBytes()));
+            System.out.println("setBytesArrayArray, bytes[][]");
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test bytes32[][] set and get
+        {
+            List<Object> params = new ArrayList<>();
+            byte[] b = Hex.decode("ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff");
+            List<byte[]> bs = new ArrayList<>();
+            bs.add(b);
+            List<List<byte[]>> bss = new ArrayList<>();
+            bss.add(bs);
+            params.add(bss);
+
+            TransactionRequest transactionRequest = requestBuilder.setMethod("setBytes32ArrayArray").buildRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransaction(transactionRequest);
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            Assert.assertEquals(Hex.toHexString(((Bytes) ((DynamicArray<?>) ((DynamicArray<?>) results.get(0)).getValue().get(0)).getValue().get(0)).getValue()), "ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff");
+            System.out.println("setBytes32ArrayArray, bytes32[][]");
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test bytes[2][] set and get
+        {
+            List<Object> params = new ArrayList<>();
+            byte[] b1 = Hex.decode("ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff");
+            byte[] b2 = DynamicBytes.DEFAULT.getValue();
+            List<byte[]> bs = new ArrayList<>();
+            bs.add(b1);
+            bs.add(b2);
+            List<List<byte[]>> bss = new ArrayList<>();
+            bss.add(bs);
+            params.add(bss);
+
+            TransactionRequest transactionRequest = requestBuilder.setMethod("setBytesStaticArrayArray").buildRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransaction(transactionRequest);
+
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            Assert.assertEquals(Hex.toHexString(((DynamicBytes) ((DynamicArray<?>) ((DynamicArray<?>) results.get(0)).getValue().get(0)).getValue().get(0)).getValue()), "ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff");
+            System.out.println("setBytesStaticArrayArray, bytes[2][]");
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test bytes32[2][] set and get
+        {
+            List<Object> params = new ArrayList<>();
+            byte[] b1 = Hex.decode("ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff");
+            byte[] b2 = Bytes32.DEFAULT.getValue();
+            List<byte[]> bs = new ArrayList<>();
+            bs.add(b1);
+            bs.add(b2);
+            List<List<byte[]>> bss = new ArrayList<>();
+            bss.add(bs);
+            params.add(bss);
+
+            TransactionRequest transactionRequest = requestBuilder.setMethod("setBytes32StaticArrayArray").buildRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransaction(transactionRequest);
+
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            Assert.assertEquals(Hex.toHexString(((Bytes) ((StaticArray<?>) ((DynamicArray<?>) results.get(0)).getValue().get(0)).getValue().get(0)).getValue()), "ffffffff1234567890123456ffffffffffffffff1234567890123456ffffffff");
+            System.out.println("setBytes32StaticArrayArray, bytes32[2][]");
+            System.out.println(JsonUtils.toJson(returnObject));
+        }
+
+        // test struct set and get
+        {
+            List<Object> params = new ArrayList<>();
+            List<String> array = new ArrayList<>();
+            array.add("test2132131");
+            List<byte[]> bytes32DynamicArray = new ArrayList<>();
+            bytes32DynamicArray.add(Bytes32.DEFAULT.getValue());
+            List<Object> structA = new ArrayList<>();
+            structA.add(array);
+            structA.add(bytes32DynamicArray);
+            params.add(structA);
+            TransactionRequest transactionRequest = requestBuilder.setMethod("buildStructB").buildRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransaction(transactionRequest);
+
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 2);
+            Assert.assertEquals(returnObject.size(), 2);
+            Assert.assertEquals(returnABIObject.size(), 2);
+            System.out.println("buildStructB, StructB, StructA[]");
+            System.out.println(JsonUtils.toJsonWithException(returnObject));
+        }
+
+        // test static struct set and get
+        {
+            List<Object> params = new ArrayList<>();
+            List<Integer> staticArray = new ArrayList<>();
+            staticArray.add(1);
+            List<Object> struct = new ArrayList<>();
+            struct.add(128);
+            struct.add(127);
+            struct.add(staticArray);
+            params.add(struct);
+
+            // use static struct params, get single struct
+            TransactionRequest transactionRequest = requestBuilder.setMethod("buildStaticStruct").buildRequest(params);
+            TransactionResponse transactionResponse = transactionService.sendTransaction(transactionRequest);
+            Assert.assertEquals(transactionResponse.getTransactionReceipt().getStatus(), 0);
+            List<Type> results = transactionResponse.getResults();
+            List<Object> returnObject = transactionResponse.getReturnObject();
+            List<ABIObject> returnABIObject = transactionResponse.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            System.out.println("buildStaticStruct, staticStruct");
+            System.out.println(JsonUtils.toJsonWithException(returnObject));
+
+            // use number params, get static struct list
+            List<Object> params2 = new ArrayList<>();
+            params2.add(256);
+            params2.add(288);
+            TransactionRequest transactionRequest1 = requestBuilder.setMethod("buildStaticStruct").buildRequest(params2);
+            TransactionResponse transactionResponse1 = transactionService.sendTransaction(transactionRequest1);
+            Assert.assertEquals(transactionResponse1.getTransactionReceipt().getStatus(), 0);
+            results = transactionResponse1.getResults();
+            returnObject = transactionResponse1.getReturnObject();
+            returnABIObject = transactionResponse1.getReturnABIObject();
+            Assert.assertEquals(results.size(), 1);
+            Assert.assertEquals(returnObject.size(), 1);
+            Assert.assertEquals(returnABIObject.size(), 1);
+            System.out.println("buildStaticStruct, staticStruct[]");
+            System.out.println(JsonUtils.toJsonWithException(returnObject));
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fisco/bcos/sdk/v3/codec/ContractCodec.java b/src/main/java/org/fisco/bcos/sdk/v3/codec/ContractCodec.java
index 9c029a1e4..03073a956 100644
--- a/src/main/java/org/fisco/bcos/sdk/v3/codec/ContractCodec.java
+++ b/src/main/java/org/fisco/bcos/sdk/v3/codec/ContractCodec.java
@@ -812,6 +812,12 @@ public Pair<List<Object>, List<ABIObject>> decodeMethodAndGetOutputObject(
         return ContractCodecTools.decodeJavaObjectAndGetOutputObject(abiObject);
     }
 
+    public Pair<List<Object>, List<ABIObject>> decodeMethodOutputAndGetObject(
+            String abi, String methodName, String output) throws ContractCodecException {
+        ABIObject abiObject = decodeMethodAndGetOutputAbiObject(abi, methodName, output);
+        return ContractCodecTools.decodeJavaObjectAndGetOutputObject(abiObject);
+    }
+
     public ABIObject decodeMethodAndGetOutAbiObjectByABIDefinition(
             ABIDefinition abiDefinition, String output) throws ContractCodecException {
         ABIObject outputABIObject = ABIObjectFactory.createOutputObject(abiDefinition);
diff --git a/src/main/java/org/fisco/bcos/sdk/v3/codec/abi/Constant.java b/src/main/java/org/fisco/bcos/sdk/v3/codec/abi/Constant.java
index 0b1f4e7d6..230f89af3 100644
--- a/src/main/java/org/fisco/bcos/sdk/v3/codec/abi/Constant.java
+++ b/src/main/java/org/fisco/bcos/sdk/v3/codec/abi/Constant.java
@@ -15,5 +15,5 @@ public class Constant {
     public static final BigInteger MIN_INT128 = MAX_INT128.negate();
 
     public static String NO_APPROPRIATE_ABI_METHOD =
-            "Cann't encode in encodeMethodFromObject with appropriate interface ABI, please check your method name or ABI file";
+            "Can't encode in encodeMethodFromObject with appropriate interface ABI, please check your method name or ABI file";
 }
diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/AssembleEIP1559TransactionService.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/AssembleEIP1559TransactionService.java
new file mode 100644
index 000000000..fc0919ab7
--- /dev/null
+++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/AssembleEIP1559TransactionService.java
@@ -0,0 +1,175 @@
+package org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2;
+
+import java.util.Objects;
+import org.fisco.bcos.sdk.jni.common.JniException;
+import org.fisco.bcos.sdk.v3.client.Client;
+import org.fisco.bcos.sdk.v3.codec.ContractCodecException;
+import org.fisco.bcos.sdk.v3.model.TransactionReceipt;
+import org.fisco.bcos.sdk.v3.model.callback.TransactionCallback;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.DeployTransactionRequest;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.DeployTransactionRequestWithStringParams;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.TransactionRequest;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.TransactionRequestWithStringParams;
+import org.fisco.bcos.sdk.v3.transaction.model.dto.TransactionResponse;
+import org.fisco.bcos.sdk.v3.utils.Hex;
+
+/**
+ * AssembleTransactionService
+ *
+ * <p>codec(abi, method, params) -> inputData sendTx(to, inputData) -> receipt decode(abi, method,
+ * receipt.output, ) -> result
+ */
+public class AssembleEIP1559TransactionService extends AssembleTransactionService {
+
+    AssembleEIP1559TransactionService(Client client) {
+        super(client);
+    }
+
+    public TransactionResponse sendEIP1559Transaction(TransactionRequest request)
+            throws ContractCodecException, JniException {
+        byte[] encodeMethod =
+                contractCodec.encodeMethod(
+                        request.getAbi(), request.getMethod(), request.getParams());
+        TransactionReceipt receipt =
+                transactionManager.sendTransactionEIP1559(
+                        request.getTo(),
+                        Hex.toHexString(encodeMethod),
+                        request.getValue(),
+                        request.getEip1559Struct(),
+                        request.getAbi(),
+                        false);
+        if (Objects.nonNull(receipt)
+                && (Objects.isNull(receipt.getInput()) || receipt.getInput().isEmpty())) {
+            receipt.setInput(Hex.toHexStringWithPrefix(encodeMethod));
+        }
+        return this.transactionDecoder.decodeReceiptWithValues(
+                request.getAbi(), request.getMethod(), receipt);
+    }
+
+    public TransactionResponse sendEIP1559TransactionWithStringParams(
+            TransactionRequestWithStringParams request)
+            throws ContractCodecException, JniException {
+        byte[] encodeMethod =
+                contractCodec.encodeMethodFromString(
+                        request.getAbi(), request.getMethod(), request.getStringParams());
+        TransactionReceipt receipt =
+                transactionManager.sendTransactionEIP1559(
+                        request.getTo(),
+                        Hex.toHexString(encodeMethod),
+                        request.getValue(),
+                        request.getEip1559Struct(),
+                        request.getAbi(),
+                        false);
+        if (Objects.nonNull(receipt)
+                && (Objects.isNull(receipt.getInput()) || receipt.getInput().isEmpty())) {
+            receipt.setInput(Hex.toHexStringWithPrefix(encodeMethod));
+        }
+        return this.transactionDecoder.decodeReceiptWithValues(
+                request.getAbi(), request.getMethod(), receipt);
+    }
+
+    public TransactionResponse deployContractEIP1559(DeployTransactionRequest request)
+            throws ContractCodecException, JniException {
+        byte[] encodeConstructor =
+                contractCodec.encodeConstructor(
+                        request.getAbi(), request.getBin(), request.getParams());
+        TransactionReceipt receipt =
+                transactionManager.sendTransactionEIP1559(
+                        request.getTo(),
+                        Hex.toHexString(encodeConstructor),
+                        request.getValue(),
+                        request.getEip1559Struct(),
+                        request.getAbi(),
+                        true);
+        if (Objects.nonNull(receipt)
+                && (Objects.isNull(receipt.getInput()) || receipt.getInput().isEmpty())) {
+            receipt.setInput(Hex.toHexStringWithPrefix(encodeConstructor));
+        }
+        return this.transactionDecoder.decodeReceiptWithValues(request.getAbi(), "", receipt);
+    }
+
+    public TransactionResponse deployContractEIP1559WithStringParams(
+            DeployTransactionRequestWithStringParams request)
+            throws ContractCodecException, JniException {
+        byte[] encodeConstructor =
+                contractCodec.encodeConstructorFromString(
+                        request.getAbi(), request.getBin(), request.getStringParams());
+        TransactionReceipt receipt =
+                transactionManager.sendTransactionEIP1559(
+                        request.getTo(),
+                        Hex.toHexString(encodeConstructor),
+                        request.getValue(),
+                        request.getEip1559Struct(),
+                        request.getAbi(),
+                        true);
+        if (Objects.nonNull(receipt)
+                && (Objects.isNull(receipt.getInput()) || receipt.getInput().isEmpty())) {
+            receipt.setInput(Hex.toHexStringWithPrefix(encodeConstructor));
+        }
+        return this.transactionDecoder.decodeReceiptWithValues(request.getAbi(), "", receipt);
+    }
+
+    public String asyncSendEIP1559Transaction(
+            TransactionRequest request, TransactionCallback callback)
+            throws ContractCodecException, JniException {
+        byte[] encodeMethod =
+                contractCodec.encodeMethod(
+                        request.getAbi(), request.getMethod(), request.getParams());
+        return transactionManager.asyncSendTransactionEIP1559(
+                request.getTo(),
+                Hex.toHexString(encodeMethod),
+                request.getValue(),
+                request.getEip1559Struct(),
+                request.getAbi(),
+                false,
+                callback);
+    }
+
+    public String asyncSendEIP1559TransactionWithStringParams(
+            TransactionRequestWithStringParams request, TransactionCallback callback)
+            throws ContractCodecException, JniException {
+        byte[] encodeMethod =
+                contractCodec.encodeMethodFromString(
+                        request.getAbi(), request.getMethod(), request.getStringParams());
+        return transactionManager.asyncSendTransactionEIP1559(
+                request.getTo(),
+                Hex.toHexString(encodeMethod),
+                request.getValue(),
+                request.getEip1559Struct(),
+                request.getAbi(),
+                false,
+                callback);
+    }
+
+    public String asyncDeployContractEIP1559(
+            DeployTransactionRequest request, TransactionCallback callback)
+            throws ContractCodecException, JniException {
+        byte[] encodeConstructor =
+                contractCodec.encodeConstructor(
+                        request.getAbi(), request.getBin(), request.getParams());
+        return transactionManager.asyncSendTransactionEIP1559(
+                request.getTo(),
+                Hex.toHexString(encodeConstructor),
+                request.getValue(),
+                request.getEip1559Struct(),
+                request.getAbi(),
+                true,
+                callback);
+    }
+
+    public String asyncDeployContractEIP1559WithStringParams(
+            DeployTransactionRequestWithStringParams request, TransactionCallback callback)
+            throws ContractCodecException, JniException {
+        byte[] encodeConstructor =
+                contractCodec.encodeConstructorFromString(
+                        request.getAbi(), request.getBin(), request.getStringParams());
+        return transactionManager.asyncSendTransactionEIP1559(
+                request.getTo(),
+                Hex.toHexString(encodeConstructor),
+                request.getValue(),
+                request.getEip1559Struct(),
+                request.getAbi(),
+                true,
+                callback);
+    }
+}
diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/AssembleTransactionService.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/AssembleTransactionService.java
index 30ec50b4d..326e8c5e7 100644
--- a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/AssembleTransactionService.java
+++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/AssembleTransactionService.java
@@ -1,12 +1,29 @@
 package org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2;
 
-import java.math.BigInteger;
 import java.util.List;
+import java.util.Objects;
+import org.apache.commons.lang3.tuple.Pair;
+import org.fisco.bcos.sdk.jni.common.JniException;
 import org.fisco.bcos.sdk.v3.client.Client;
+import org.fisco.bcos.sdk.v3.client.protocol.response.Call;
 import org.fisco.bcos.sdk.v3.codec.ContractCodec;
+import org.fisco.bcos.sdk.v3.codec.ContractCodecException;
+import org.fisco.bcos.sdk.v3.codec.wrapper.ABIObject;
+import org.fisco.bcos.sdk.v3.model.Response;
+import org.fisco.bcos.sdk.v3.model.RetCode;
+import org.fisco.bcos.sdk.v3.model.TransactionReceipt;
+import org.fisco.bcos.sdk.v3.model.callback.RespCallback;
 import org.fisco.bcos.sdk.v3.model.callback.TransactionCallback;
-import org.fisco.bcos.sdk.v3.transaction.gasProvider.EIP1559Struct;
+import org.fisco.bcos.sdk.v3.transaction.codec.decode.ReceiptParser;
+import org.fisco.bcos.sdk.v3.transaction.codec.decode.TransactionDecoderInterface;
+import org.fisco.bcos.sdk.v3.transaction.codec.decode.TransactionDecoderService;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.DeployTransactionRequest;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.DeployTransactionRequestWithStringParams;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.TransactionRequest;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.TransactionRequestWithStringParams;
+import org.fisco.bcos.sdk.v3.transaction.model.dto.CallResponse;
 import org.fisco.bcos.sdk.v3.transaction.model.dto.TransactionResponse;
+import org.fisco.bcos.sdk.v3.utils.Hex;
 
 /**
  * AssembleTransactionService
@@ -15,247 +32,268 @@
  * receipt.output, ) -> result
  */
 public class AssembleTransactionService {
-    private TransactionManager transactionManager;
+    protected TransactionManager transactionManager;
+    protected final TransactionDecoderInterface transactionDecoder;
+    protected final ContractCodec contractCodec;
+    protected final Client client;
 
-    private final ContractCodec contractCodec;
-
-    AssembleTransactionService(Client client) {
+    public AssembleTransactionService(Client client) {
+        this.client = client;
         this.contractCodec =
                 new ContractCodec(client.getCryptoSuite().getHashImpl(), client.isWASM());
-        transactionManager = new DefaultTransactionManager(client);
+        this.transactionManager = new DefaultTransactionManager(client);
+        this.transactionDecoder =
+                new TransactionDecoderService(
+                        client.getCryptoSuite().getHashImpl(), client.isWASM());
     }
 
     public void setTransactionManager(TransactionManager transactionManager) {
         this.transactionManager = transactionManager;
     }
 
-    public TransactionResponse sendTransaction(
-            String abi, String method, List<Object> params, String to, BigInteger value) {
-        return null;
-    }
-
-    public TransactionResponse sendTransaction(
-            String abi,
-            String method,
-            List<Object> params,
-            String to,
-            BigInteger value,
-            BigInteger gasPrice,
-            BigInteger gasLimit) {
-        return null;
+    public TransactionResponse sendTransaction(TransactionRequest request)
+            throws ContractCodecException, JniException {
+        byte[] encodeMethod =
+                contractCodec.encodeMethod(
+                        request.getAbi(), request.getMethod(), request.getParams());
+        TransactionReceipt receipt =
+                transactionManager.sendTransaction(
+                        request.getTo(),
+                        Hex.toHexString(encodeMethod),
+                        request.getValue(),
+                        request.getGasPrice(),
+                        request.getGasLimit(),
+                        request.getAbi(),
+                        false);
+        if (Objects.nonNull(receipt)
+                && (Objects.isNull(receipt.getInput()) || receipt.getInput().isEmpty())) {
+            receipt.setInput(Hex.toHexStringWithPrefix(encodeMethod));
+        }
+        return this.transactionDecoder.decodeReceiptWithValues(
+                request.getAbi(), request.getMethod(), receipt);
     }
 
     public TransactionResponse sendTransactionWithStringParams(
-            String abi,
-            String method,
-            List<String> params,
-            String to,
-            BigInteger value,
-            BigInteger gasPrice,
-            BigInteger gasLimit) {
-        return null;
-    }
-
-    public TransactionResponse sendTransactionWithStringParams(
-            String abi, String method, List<String> params, String to, BigInteger value) {
-        return null;
-    }
-
-    public TransactionResponse deployContract(
-            String abi, String bin, List<Object> params, BigInteger value) {
-        return null;
-    }
-
-    public TransactionResponse deployContractWithStringParams(
-            String abi, String bin, List<String> params, BigInteger value) {
-        return null;
+            TransactionRequestWithStringParams request)
+            throws ContractCodecException, JniException {
+        byte[] transactionData =
+                contractCodec.encodeMethodFromString(
+                        request.getAbi(), request.getMethod(), request.getStringParams());
+        TransactionReceipt receipt =
+                transactionManager.sendTransaction(
+                        request.getTo(),
+                        Hex.toHexString(transactionData),
+                        request.getValue(),
+                        request.getGasPrice(),
+                        request.getGasLimit(),
+                        request.getAbi(),
+                        false);
+        if (Objects.nonNull(receipt)
+                && (Objects.isNull(receipt.getInput()) || receipt.getInput().isEmpty())) {
+            receipt.setInput(Hex.toHexStringWithPrefix(transactionData));
+        }
+        return this.transactionDecoder.decodeReceiptWithValues(
+                request.getAbi(), request.getMethod(), receipt);
     }
 
-    public TransactionResponse deployContract(
-            String abi,
-            String bin,
-            List<Object> params,
-            BigInteger value,
-            BigInteger gasPrice,
-            BigInteger gasLimit) {
-        return null;
+    public TransactionResponse deployContract(DeployTransactionRequest request)
+            throws ContractCodecException, JniException {
+        byte[] encodeConstructor =
+                contractCodec.encodeConstructor(
+                        request.getAbi(), request.getBin(), request.getParams());
+        TransactionReceipt receipt =
+                transactionManager.sendTransaction(
+                        request.getTo(),
+                        Hex.toHexString(encodeConstructor),
+                        request.getValue(),
+                        request.getGasPrice(),
+                        request.getGasLimit(),
+                        request.getAbi(),
+                        true);
+        if (Objects.nonNull(receipt)
+                && (Objects.isNull(receipt.getInput()) || receipt.getInput().isEmpty())) {
+            receipt.setInput(Hex.toHexStringWithPrefix(encodeConstructor));
+        }
+        return this.transactionDecoder.decodeReceiptWithoutValues(request.getAbi(), receipt);
     }
 
     public TransactionResponse deployContractWithStringParams(
-            String abi,
-            String bin,
-            List<String> params,
-            BigInteger value,
-            BigInteger gasPrice,
-            BigInteger gasLimit) {
-        return null;
-    }
-
-    public TransactionResponse sendEIP1559Transaction(
-            String abi,
-            String method,
-            List<Object> params,
-            String to,
-            BigInteger value,
-            EIP1559Struct eip1559Struct) {
-        return null;
-    }
-
-    public TransactionResponse sendEIP1559TransactionWithStringParams(
-            String abi,
-            String method,
-            List<String> params,
-            String to,
-            BigInteger value,
-            EIP1559Struct eip1559Struct) {
-        return null;
-    }
-
-    public TransactionResponse deployContractEIP1559(
-            String abi,
-            String method,
-            List<Object> params,
-            String to,
-            BigInteger value,
-            EIP1559Struct eip1559Struct) {
-        return null;
-    }
-
-    public TransactionResponse deployContractEIP1559WithStringParams(
-            String abi,
-            String method,
-            List<String> params,
-            String to,
-            BigInteger value,
-            EIP1559Struct eip1559Struct) {
-        return null;
-    }
-
-    public String asyncSendTransaction(
-            String abi,
-            String method,
-            List<Object> params,
-            String to,
-            BigInteger value,
-            TransactionCallback callback) {
-        return null;
+            DeployTransactionRequestWithStringParams request)
+            throws ContractCodecException, JniException {
+        byte[] encodedConstructor =
+                contractCodec.encodeConstructorFromString(
+                        request.getAbi(), request.getBin(), request.getStringParams());
+        TransactionReceipt receipt =
+                transactionManager.sendTransaction(
+                        request.getTo(),
+                        Hex.toHexString(encodedConstructor),
+                        request.getValue(),
+                        request.getGasPrice(),
+                        request.getGasLimit(),
+                        request.getAbi(),
+                        true);
+        if (Objects.nonNull(receipt)
+                && (Objects.isNull(receipt.getInput()) || receipt.getInput().isEmpty())) {
+            receipt.setInput(Hex.toHexStringWithPrefix(encodedConstructor));
+        }
+        return this.transactionDecoder.decodeReceiptWithoutValues(request.getAbi(), receipt);
     }
 
-    public String asyncSendTransactionWithStringParams(
-            String abi,
-            String method,
-            List<String> params,
-            String to,
-            BigInteger value,
-            TransactionCallback callback) {
-        return null;
-    }
-
-    public String asyncSendTransaction(
-            String abi,
-            String method,
-            List<Object> params,
-            String to,
-            BigInteger value,
-            BigInteger gasPrice,
-            BigInteger gasLimit,
-            TransactionCallback callback) {
-        return null;
+    public String asyncSendTransaction(TransactionRequest request, TransactionCallback callback)
+            throws ContractCodecException, JniException {
+        byte[] encodeMethod =
+                contractCodec.encodeMethod(
+                        request.getAbi(), request.getMethod(), request.getParams());
+        return transactionManager.asyncSendTransaction(
+                request.getTo(),
+                Hex.toHexString(encodeMethod),
+                request.getValue(),
+                request.getGasPrice(),
+                request.getGasLimit(),
+                request.getAbi(),
+                false,
+                callback);
     }
 
     public String asyncSendTransactionWithStringParams(
-            String abi,
-            String method,
-            List<String> params,
-            String to,
-            BigInteger value,
-            BigInteger gasPrice,
-            BigInteger gasLimit,
-            TransactionCallback callback) {
-        return null;
+            TransactionRequestWithStringParams request, TransactionCallback callback)
+            throws ContractCodecException, JniException {
+        byte[] encodeMethodFromString =
+                contractCodec.encodeMethodFromString(
+                        request.getAbi(), request.getMethod(), request.getStringParams());
+        return transactionManager.asyncSendTransaction(
+                request.getTo(),
+                Hex.toHexString(encodeMethodFromString),
+                request.getValue(),
+                request.getGasPrice(),
+                request.getGasLimit(),
+                request.getAbi(),
+                false,
+                callback);
     }
 
     public String asyncDeployContract(
-            String abi,
-            String bin,
-            List<Object> params,
-            BigInteger value,
-            TransactionCallback callback) {
-        return null;
+            DeployTransactionRequest request, TransactionCallback callback)
+            throws ContractCodecException, JniException {
+        byte[] encodeConstructor =
+                contractCodec.encodeConstructor(
+                        request.getAbi(), request.getBin(), request.getParams());
+        return transactionManager.asyncSendTransaction(
+                request.getTo(),
+                Hex.toHexString(encodeConstructor),
+                request.getValue(),
+                request.getGasPrice(),
+                request.getGasLimit(),
+                request.getAbi(),
+                true,
+                callback);
     }
 
     public String asyncDeployContractWithStringParams(
-            String abi,
-            String bin,
-            List<String> params,
-            BigInteger value,
-            TransactionCallback callback) {
-        return null;
+            DeployTransactionRequestWithStringParams request, TransactionCallback callback)
+            throws JniException, ContractCodecException {
+        byte[] encodeConstructorFromString =
+                contractCodec.encodeConstructorFromString(
+                        request.getAbi(), request.getBin(), request.getStringParams());
+        return transactionManager.asyncSendTransaction(
+                request.getTo(),
+                Hex.toHexString(encodeConstructorFromString),
+                request.getValue(),
+                request.getGasPrice(),
+                request.getGasLimit(),
+                request.getAbi(),
+                true,
+                callback);
     }
 
-    public String asyncDeployContract(
-            String abi,
-            String bin,
-            List<Object> params,
-            BigInteger value,
-            BigInteger gasPrice,
-            BigInteger gasLimit,
-            TransactionCallback callback) {
-        return null;
+    public CallResponse sendCall(TransactionRequest request)
+            throws ContractCodecException, JniException {
+        byte[] encodeMethod =
+                contractCodec.encodeMethod(
+                        request.getAbi(), request.getMethod(), request.getParams());
+        Call call = transactionManager.sendCall(request.getTo(), Hex.toHexString(encodeMethod));
+        return parseCallResponse(request, call);
     }
 
-    public String asyncDeployContractWithStringParams(
-            String abi,
-            String bin,
-            List<String> params,
-            BigInteger value,
-            BigInteger gasPrice,
-            BigInteger gasLimit,
-            TransactionCallback callback) {
-        return null;
+    public CallResponse sendCallWithStringParams(TransactionRequestWithStringParams request)
+            throws ContractCodecException, JniException {
+        byte[] encodeMethodFromString =
+                contractCodec.encodeMethodFromString(
+                        request.getAbi(), request.getMethod(), request.getStringParams());
+        Call call =
+                transactionManager.sendCall(
+                        request.getTo(), Hex.toHexString(encodeMethodFromString));
+        return parseCallResponse(request, call);
     }
 
-    public String asyncSendEIP1559Transaction(
-            String abi,
-            String method,
-            List<Object> params,
-            String to,
-            BigInteger value,
-            EIP1559Struct eip1559Struct,
-            TransactionCallback callback) {
-        return null;
-    }
+    public void asyncSendCall(TransactionRequest request, RespCallback<CallResponse> callback)
+            throws ContractCodecException, JniException {
+        byte[] encodeMethod =
+                contractCodec.encodeMethod(
+                        request.getAbi(), request.getMethod(), request.getParams());
+        transactionManager.asyncSendCall(
+                request.getTo(),
+                Hex.toHexString(encodeMethod),
+                new RespCallback<Call>() {
+                    @Override
+                    public void onResponse(Call call) {
+                        try {
+                            callback.onResponse(parseCallResponse(request, call));
+                        } catch (ContractCodecException e) {
+                            Response response = new Response();
+                            response.setErrorCode(-1);
+                            response.setErrorMessage(e.getMessage());
+                            callback.onError(response);
+                        }
+                    }
 
-    public String asyncSendEIP1559TransactionWithStringParams(
-            String abi,
-            String method,
-            List<String> params,
-            String to,
-            BigInteger value,
-            EIP1559Struct eip1559Struct,
-            TransactionCallback callback) {
-        return null;
+                    @Override
+                    public void onError(Response errorResponse) {
+                        callback.onError(errorResponse);
+                    }
+                });
     }
 
-    public String asyncDeployContractEIP1559(
-            String abi,
-            String bin,
-            List<Object> params,
-            String to,
-            BigInteger value,
-            EIP1559Struct eip1559Struct,
-            TransactionCallback callback) {
-        return null;
+    public void asyncSendCallWithStringParams(
+            TransactionRequestWithStringParams request, RespCallback<CallResponse> callback)
+            throws ContractCodecException, JniException {
+        byte[] encodeMethodFromString =
+                contractCodec.encodeMethodFromString(
+                        request.getAbi(), request.getMethod(), request.getStringParams());
+        transactionManager.asyncSendCall(
+                request.getTo(),
+                Hex.toHexString(encodeMethodFromString),
+                new RespCallback<Call>() {
+                    @Override
+                    public void onResponse(Call call) {
+                        try {
+                            callback.onResponse(parseCallResponse(request, call));
+                        } catch (ContractCodecException e) {
+                            Response response = new Response();
+                            response.setErrorCode(-1);
+                            response.setErrorMessage(e.getMessage());
+                            callback.onError(response);
+                        }
+                    }
+
+                    @Override
+                    public void onError(Response errorResponse) {
+                        callback.onError(errorResponse);
+                    }
+                });
     }
 
-    public String asyncDeployContractEIP1559WithStringParams(
-            String abi,
-            String bin,
-            List<String> params,
-            String to,
-            BigInteger value,
-            EIP1559Struct eip1559Struct,
-            TransactionCallback callback) {
-        return null;
+    private CallResponse parseCallResponse(TransactionRequest request, Call call)
+            throws ContractCodecException {
+        CallResponse callResponse = new CallResponse();
+        RetCode retCode = ReceiptParser.parseCallOutput(call.getCallResult(), "");
+        callResponse.setReturnCode(call.getCallResult().getStatus());
+        callResponse.setReturnMessage(retCode.getMessage());
+        Pair<List<Object>, List<ABIObject>> methodOutputAndGetObject =
+                contractCodec.decodeMethodOutputAndGetObject(
+                        request.getAbi(), request.getMethod(), call.getCallResult().getOutput());
+        callResponse.setReturnObject(methodOutputAndGetObject.getLeft());
+        callResponse.setReturnABIObject(methodOutputAndGetObject.getRight());
+        return callResponse;
     }
 }
diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/DefaultTransactionManager.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/DefaultTransactionManager.java
index 922c2923c..6dd57aa3c 100644
--- a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/DefaultTransactionManager.java
+++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/DefaultTransactionManager.java
@@ -140,13 +140,13 @@ protected TransactionReceipt sendTransaction(
                         client.getCryptoSuite().getCryptoKeyPair().getJniKeyPair(),
                         client.getGroup(),
                         client.getChainId(),
-                        to,
+                        to == null ? "" : to,
                         data,
-                        abi,
+                        (abi == null || !constructor) ? "" : abi,
                         blockLimit.longValue(),
                         Numeric.toHexString(value),
                         Numeric.toHexString(gasPrice),
-                        gasLimit.longValue(),
+                        gasLimit == null ? 0 : gasLimit.longValue(),
                         transactionAttribute,
                         client.getExtraData());
 
@@ -268,13 +268,13 @@ protected String asyncSendTransaction(
                         client.getCryptoSuite().getCryptoKeyPair().getJniKeyPair(),
                         client.getGroup(),
                         client.getChainId(),
-                        to,
+                        to == null ? "" : to,
                         data,
-                        abi,
+                        (abi == null || !constructor) ? "" : abi,
                         blockLimit.longValue(),
                         Numeric.toHexString(value),
                         Numeric.toHexString(gasPrice),
-                        gasLimit.longValue(),
+                        gasLimit == null ? 0 : gasLimit.longValue(),
                         transactionAttribute,
                         client.getExtraData());
         client.sendTransactionAsync(txPair.getSignedTx(), false, callback);
@@ -342,9 +342,9 @@ protected TransactionReceipt sendTransactionEIP1559(
                         client.getCryptoSuite().getCryptoKeyPair().getJniKeyPair(),
                         client.getGroup(),
                         client.getChainId(),
-                        to,
+                        to == null ? "" : to,
                         data,
-                        abi,
+                        (abi == null || !constructor) ? "" : abi,
                         blockLimit.longValue(),
                         Numeric.toHexString(value),
                         Numeric.toHexString(eip1559Struct.getMaxFeePerGas()),
@@ -420,9 +420,9 @@ protected String asyncSendTransactionEIP1559(
                         client.getCryptoSuite().getCryptoKeyPair().getJniKeyPair(),
                         client.getGroup(),
                         client.getChainId(),
-                        to,
+                        to == null ? "" : to,
                         data,
-                        abi,
+                        (abi == null || !constructor) ? "" : abi,
                         blockLimit.longValue(),
                         Numeric.toHexString(value),
                         Numeric.toHexString(eip1559Struct.getMaxFeePerGas()),
diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/ProxySignTransactionManager.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/ProxySignTransactionManager.java
index feefd1cc4..b53be3145 100644
--- a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/ProxySignTransactionManager.java
+++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/ProxySignTransactionManager.java
@@ -153,9 +153,9 @@ protected TransactionReceipt sendTransaction(
                 TransactionBuilderV2JniObj.createTransactionData(
                         client.getGroup(),
                         client.getChainId(),
-                        to,
+                        to == null ? "" : to,
                         data,
-                        abi,
+                        (abi == null || !constructor) ? "" : abi,
                         blockLimit.longValue(),
                         Numeric.toHexString(value),
                         Numeric.toHexString(gasPrice),
@@ -340,9 +340,9 @@ protected String asyncSendTransaction(
                 TransactionBuilderV2JniObj.createTransactionData(
                         client.getGroup(),
                         client.getChainId(),
-                        to,
+                        to == null ? "" : to,
                         data,
-                        abi,
+                        (abi == null || !constructor) ? "" : abi,
                         blockLimit.longValue(),
                         Numeric.toHexString(value),
                         Numeric.toHexString(gasPrice),
@@ -451,9 +451,9 @@ protected TransactionReceipt sendTransactionEIP1559(
                 TransactionBuilderV2JniObj.createEIP1559TransactionData(
                         client.getGroup(),
                         client.getChainId(),
-                        to,
+                        to == null ? "" : to,
                         data,
-                        abi,
+                        (abi == null || !constructor) ? "" : abi,
                         blockLimit.longValue(),
                         Numeric.toHexString(value),
                         eip1559Struct.getGasLimit().longValue(),
@@ -564,9 +564,9 @@ protected String asyncSendTransactionEIP1559(
                 TransactionBuilderV2JniObj.createEIP1559TransactionData(
                         client.getGroup(),
                         client.getChainId(),
-                        to,
+                        to == null ? "" : to,
                         data,
-                        abi,
+                        (abi == null || !constructor) ? "" : abi,
                         blockLimit.longValue(),
                         Numeric.toHexString(value),
                         eip1559Struct.getGasLimit().longValue(),
diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/TransactionManager.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/TransactionManager.java
index 4b17bd437..1c6ba5394 100644
--- a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/TransactionManager.java
+++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/TransactionManager.java
@@ -19,6 +19,14 @@ public Client getClient() {
     }
 
     protected TransactionManager(Client client) {
+        // FIXME: negotiate protocol not set
+        //        int negotiatedProtocol = client.getNegotiatedProtocol();
+        //        int maxProtocol = negotiatedProtocol >> 16;
+        //        if (maxProtocol < 1) {
+        //            throw new UnsupportedOperationException(
+        //                    "The current version of the node does not support the transaction
+        // manager");
+        //        }
         this.client = client;
     }
 
diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/DeployTransactionRequest.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/DeployTransactionRequest.java
new file mode 100644
index 000000000..2e89fc68e
--- /dev/null
+++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/DeployTransactionRequest.java
@@ -0,0 +1,48 @@
+package org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto;
+
+import java.math.BigInteger;
+import org.fisco.bcos.sdk.v3.transaction.gasProvider.EIP1559Struct;
+
+public class DeployTransactionRequest extends TransactionRequest {
+
+    private String bin;
+
+    public DeployTransactionRequest(
+            String abi,
+            String bin,
+            BigInteger value,
+            BigInteger gasPrice,
+            BigInteger gasLimit,
+            EIP1559Struct eip1559Struct) {
+        super(abi, null, null, value, gasPrice, gasLimit, eip1559Struct);
+        this.bin = bin;
+    }
+
+    public String getBin() {
+        return bin;
+    }
+
+    public void setBin(String bin) {
+        this.bin = bin;
+    }
+
+    public void setTo(String to) {
+        this.to = to;
+    }
+
+    @Override
+    public boolean isTransactionEssentialSatisfy() {
+        return super.isTransactionEssentialSatisfy() && bin != null;
+    }
+
+    @Override
+    public String toString() {
+        return "DeployTransactionRequest{"
+                + "base="
+                + super.toString()
+                + ", bin='"
+                + bin
+                + '\''
+                + "} ";
+    }
+}
diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/DeployTransactionRequestWithStringParams.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/DeployTransactionRequestWithStringParams.java
new file mode 100644
index 000000000..71ac0c224
--- /dev/null
+++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/DeployTransactionRequestWithStringParams.java
@@ -0,0 +1,43 @@
+package org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto;
+
+import java.math.BigInteger;
+import java.util.List;
+import org.fisco.bcos.sdk.v3.transaction.gasProvider.EIP1559Struct;
+
+public class DeployTransactionRequestWithStringParams extends DeployTransactionRequest {
+
+    private List<String> stringParams;
+
+    public DeployTransactionRequestWithStringParams(
+            String abi,
+            String bin,
+            BigInteger value,
+            BigInteger gasPrice,
+            BigInteger gasLimit,
+            EIP1559Struct eip1559Struct) {
+        super(abi, bin, value, gasPrice, gasLimit, eip1559Struct);
+    }
+
+    public void setStringParams(List<String> params) {
+        this.stringParams = params;
+    }
+
+    public List<String> getStringParams() {
+        return stringParams;
+    }
+
+    @Override
+    public boolean isTransactionEssentialSatisfy() {
+        return super.isTransactionEssentialSatisfy() && stringParams != null;
+    }
+
+    @Override
+    public String toString() {
+        return "DeployTransactionRequestWithStringParams{"
+                + "to='"
+                + to
+                + '\''
+                + "} "
+                + super.toString();
+    }
+}
diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/TransactionRequest.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/TransactionRequest.java
new file mode 100644
index 000000000..b7f59d4a0
--- /dev/null
+++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/TransactionRequest.java
@@ -0,0 +1,98 @@
+package org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto;
+
+import java.math.BigInteger;
+import java.util.List;
+import org.fisco.bcos.sdk.v3.transaction.gasProvider.EIP1559Struct;
+
+public class TransactionRequest {
+    private String abi;
+    private String method;
+    protected String to;
+    private List<Object> params;
+    private BigInteger value;
+    private BigInteger gasPrice;
+    private BigInteger gasLimit;
+    private EIP1559Struct eip1559Struct;
+
+    public TransactionRequest(
+            String abi,
+            String method,
+            String to,
+            BigInteger value,
+            BigInteger gasPrice,
+            BigInteger gasLimit,
+            EIP1559Struct eip1559Struct) {
+        this.abi = abi;
+        this.method = method;
+        this.to = to;
+        this.value = value;
+        this.gasPrice = gasPrice;
+        this.gasLimit = gasLimit;
+        this.eip1559Struct = eip1559Struct;
+    }
+
+    public void setParams(List<Object> params) {
+        this.params = params;
+    }
+
+    public String getAbi() {
+        return abi;
+    }
+
+    public String getMethod() {
+        return method;
+    }
+
+    public String getTo() {
+        return to;
+    }
+
+    public List<Object> getParams() {
+        return params;
+    }
+
+    public BigInteger getValue() {
+        return value;
+    }
+
+    public BigInteger getGasPrice() {
+        return gasPrice;
+    }
+
+    public BigInteger getGasLimit() {
+        return gasLimit;
+    }
+
+    public EIP1559Struct getEip1559Struct() {
+        return eip1559Struct;
+    }
+
+    public boolean isTransactionEssentialSatisfy() {
+        return abi != null && method != null && to != null;
+    }
+
+    @Override
+    public String toString() {
+        return "TransactionRequest{"
+                + "abi='"
+                + abi
+                + '\''
+                + ", method='"
+                + method
+                + '\''
+                + ", to='"
+                + to
+                + '\''
+                + ", params="
+                + params
+                + ", value="
+                + value
+                + ", gasPrice="
+                + gasPrice
+                + ", gasLimit="
+                + gasLimit
+                + ", eip1559Struct="
+                + eip1559Struct
+                + '}';
+    }
+}
diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/TransactionRequestWithStringParams.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/TransactionRequestWithStringParams.java
new file mode 100644
index 000000000..0798208f8
--- /dev/null
+++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/dto/TransactionRequestWithStringParams.java
@@ -0,0 +1,44 @@
+package org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto;
+
+import java.math.BigInteger;
+import java.util.List;
+import org.fisco.bcos.sdk.v3.transaction.gasProvider.EIP1559Struct;
+
+public class TransactionRequestWithStringParams extends TransactionRequest {
+
+    private List<String> stringParams;
+
+    public TransactionRequestWithStringParams(
+            String abi,
+            String method,
+            String to,
+            BigInteger value,
+            BigInteger gasPrice,
+            BigInteger gasLimit,
+            EIP1559Struct eip1559Struct) {
+        super(abi, method, to, value, gasPrice, gasLimit, eip1559Struct);
+    }
+
+    public void setStringParams(List<String> params) {
+        this.stringParams = params;
+    }
+
+    public List<String> getStringParams() {
+        return stringParams;
+    }
+
+    @Override
+    public boolean isTransactionEssentialSatisfy() {
+        return super.isTransactionEssentialSatisfy() && stringParams != null;
+    }
+
+    @Override
+    public String toString() {
+        return "TransactionRequestWithStringParams{"
+                + "base="
+                + super.toString()
+                + ", params="
+                + stringParams
+                + "} ";
+    }
+}
diff --git a/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/utils/TransactionRequestBuilder.java b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/utils/TransactionRequestBuilder.java
new file mode 100644
index 000000000..d78012850
--- /dev/null
+++ b/src/main/java/org/fisco/bcos/sdk/v3/transaction/manager/Transactionv2/utils/TransactionRequestBuilder.java
@@ -0,0 +1,150 @@
+package org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.utils;
+
+import java.math.BigInteger;
+import java.util.List;
+import org.fisco.bcos.sdk.v3.transaction.gasProvider.EIP1559Struct;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.DeployTransactionRequest;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.DeployTransactionRequestWithStringParams;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.TransactionRequest;
+import org.fisco.bcos.sdk.v3.transaction.manager.Transactionv2.dto.TransactionRequestWithStringParams;
+import org.fisco.bcos.sdk.v3.transaction.model.exception.ContractException;
+
+public class TransactionRequestBuilder {
+    private String abi;
+    private String method;
+    private String to;
+    private BigInteger value;
+    private BigInteger gasPrice;
+    private BigInteger gasLimit;
+    private String bin;
+    private EIP1559Struct eip1559Struct;
+
+    public TransactionRequestBuilder(String abi, String method, String to) {
+        this.abi = abi;
+        this.method = method;
+        this.to = to;
+    }
+
+    public TransactionRequestBuilder(String abi, String bin) {
+        this.abi = abi;
+        this.bin = bin;
+    }
+
+    public TransactionRequestBuilder setMethod(String method) {
+        this.method = method;
+        return this;
+    }
+
+    public TransactionRequestBuilder setTo(String to) {
+        this.to = to;
+        return this;
+    }
+
+    public TransactionRequestBuilder setValue(BigInteger value) {
+        this.value = value;
+        return this;
+    }
+
+    public TransactionRequestBuilder setGasPrice(BigInteger gasPrice) {
+        this.gasPrice = gasPrice;
+        return this;
+    }
+
+    public TransactionRequestBuilder setGasLimit(BigInteger gasLimit) {
+        this.gasLimit = gasLimit;
+        return this;
+    }
+
+    public TransactionRequestBuilder setEIP1559Struct(EIP1559Struct eip1559Struct) {
+        this.eip1559Struct = eip1559Struct;
+        return this;
+    }
+
+    public TransactionRequestBuilder setBin(String bin) {
+        this.bin = bin;
+        return this;
+    }
+
+    public TransactionRequest buildRequest(List<Object> params) throws ContractException {
+        if (params == null) {
+            throw new ContractException("SendTransaction params is null, please set it manually.");
+        }
+        TransactionRequest sendTransactionRequest =
+                new TransactionRequest(
+                        this.abi,
+                        this.method,
+                        this.to,
+                        this.value,
+                        this.gasPrice,
+                        this.gasLimit,
+                        this.eip1559Struct);
+        sendTransactionRequest.setParams(params);
+        return sendTransactionRequest;
+    }
+
+    public TransactionRequestWithStringParams buildStringParamsRequest(List<String> stringParams)
+            throws ContractException {
+        if (stringParams == null) {
+            throw new ContractException("SendTransaction params is null, please set it manually.");
+        }
+        TransactionRequestWithStringParams request =
+                new TransactionRequestWithStringParams(
+                        this.abi,
+                        this.method,
+                        this.to,
+                        this.value,
+                        this.gasPrice,
+                        this.gasLimit,
+                        this.eip1559Struct);
+        request.setStringParams(stringParams);
+        return request;
+    }
+
+    public DeployTransactionRequest buildDeployRequest(List<Object> params)
+            throws ContractException {
+        if (params == null) {
+            throw new ContractException("SendTransaction params is null, please set it manually.");
+        }
+        if (bin == null || bin.isEmpty()) {
+            throw new ContractException(
+                    "Deploy contract bin is null or empty, please set it manually.");
+        }
+        DeployTransactionRequest request =
+                new DeployTransactionRequest(
+                        this.abi,
+                        this.bin,
+                        this.value,
+                        this.gasPrice,
+                        this.gasLimit,
+                        this.eip1559Struct);
+        if (to != null) {
+            request.setTo(to);
+        }
+        request.setParams(params);
+        return request;
+    }
+
+    public DeployTransactionRequestWithStringParams buildDeployStringParamsRequest(
+            List<String> stringParams) throws ContractException {
+        if (stringParams == null) {
+            throw new ContractException("SendTransaction params is null, please set it manually.");
+        }
+        if (bin == null || bin.isEmpty()) {
+            throw new ContractException(
+                    "Deploy contract bin is null or empty, please set it manually.");
+        }
+        DeployTransactionRequestWithStringParams request =
+                new DeployTransactionRequestWithStringParams(
+                        this.abi,
+                        this.bin,
+                        this.value,
+                        this.gasPrice,
+                        this.gasLimit,
+                        this.eip1559Struct);
+        if (to != null) {
+            request.setTo(to);
+        }
+        request.setStringParams(stringParams);
+        return request;
+    }
+}
diff --git a/src/main/java/org/fisco/bcos/sdk/v3/utils/Numeric.java b/src/main/java/org/fisco/bcos/sdk/v3/utils/Numeric.java
index 1cfe1728b..1ea56494f 100644
--- a/src/main/java/org/fisco/bcos/sdk/v3/utils/Numeric.java
+++ b/src/main/java/org/fisco/bcos/sdk/v3/utils/Numeric.java
@@ -112,6 +112,9 @@ public static String toHexStringNoPrefix(BigInteger value) {
     }
 
     public static String toHexString(BigInteger value) {
+        if (value == null) {
+            return "0x0";
+        }
         return Hex.addPrefix(value.toString(16));
     }