Skip to content

Commit

Permalink
Merge pull request #349 from nervosnetwork/rc/v0.35.1
Browse files Browse the repository at this point in the history
Rc/v0.35.1
  • Loading branch information
duanyytop authored Aug 26, 2020
2 parents b8e4313 + efff2c2 commit a8ce6d6
Show file tree
Hide file tree
Showing 11 changed files with 399 additions and 5 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [v0.35.1](https://github.com/nervosnetwork/ckb-sdk-java/compare/v0.35.0...v0.35.1) (2020-8-26)

### Feature

* Add a `ckb-indexer` example ([0f4eeda](https://github.com/nervosnetwork/ckb-sdk-java/commit/0f4eeda0805fcf8eaa9b9e2b028b35dd246762fc))

### BugFix

* Fix transaction fee calculating bug ([6bb687e](https://github.com/nervosnetwork/ckb-sdk-java/commit/6bb687ef4cf2c78582bac138eb002b499e6a1544))
* Fix witnesses updating bug ([7873fe4](https://github.com/nervosnetwork/ckb-sdk-java/commit/7873fe43681005aaaf37d05dd0ccfa134efa1ce1))


# [v0.35.0](https://github.com/nervosnetwork/ckb-sdk-java/compare/v0.34.0...v0.35.0) (2020-8-25)

### Feature
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ allprojects {
targetCompatibility = 1.8

group 'org.nervos.ckb'
version '0.35.0'
version '0.35.1'

apply plugin: 'java'

Expand Down Expand Up @@ -113,7 +113,7 @@ configure(subprojects.findAll { it.name != 'tests' }) {
publications {
mavenJava(MavenPublication) {
groupId 'org.nervos.ckb'
version '0.35.0'
version '0.35.1'
from components.java
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public CollectResult collectInputs(
Iterator<TransactionInput> iterator)
throws IOException {

List<String> lockHashes = new ArrayList<>();
Set<String> lockHashes = new LinkedHashSet<>();
for (String address : addresses) {
AddressParseResult addressParseResult = AddressParser.parse(address);
lockHashes.add(addressParseResult.script.computeHash());
Expand Down Expand Up @@ -96,7 +96,7 @@ public CollectResult collectInputs(
// update witness of group first element
int witnessIndex = 0;
for (String hash : lockHashes) {
if (lockInputsMap.get(hash).size() == 0) break;
if (lockInputsMap.get(hash).size() == 0) continue;
witnesses.set(witnessIndex, new Witness(getZeros(initialLength)));
witnessIndex += lockInputsMap.get(hash).size();
}
Expand All @@ -120,10 +120,11 @@ public CollectResult collectInputs(
BigInteger changeCapacity =
inputsCapacity.subtract(needCapacity.add(calculateTxFee(transaction, feeRate)));
List<CellsWithAddress> cellsWithAddresses = new ArrayList<>();
List<String> lockHashList = Arrays.asList(lockHashes.toArray(new String[0]));
for (Map.Entry<String, List<CellInput>> entry : lockInputsMap.entrySet()) {
cellsWithAddresses.add(
new CellsWithAddress(
entry.getValue(), addresses.get(lockHashes.indexOf(entry.getKey()))));
entry.getValue(), addresses.get(lockHashList.indexOf(entry.getKey()))));
}
if (tx.inputs != null && tx.inputs.size() > 0) {
cellsWithAddresses.get(0).inputs.addAll(0, tx.inputs);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package org.nervos.ckb;

import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.nervos.ckb.crypto.secp256k1.Sign;
import org.nervos.ckb.service.Api;
import org.nervos.ckb.service.CkbIndexerApi;
import org.nervos.ckb.transaction.*;
import org.nervos.ckb.type.Witness;
import org.nervos.ckb.type.cell.CellOutput;
import org.nervos.ckb.type.transaction.Transaction;
import org.nervos.ckb.utils.Utils;

/** Copyright © 2019 Nervos Foundation. All rights reserved. */
public class SingleSigWithCkbIndexerTxExample {

private static final String NODE_URL = "http://localhost:8118";
private static final String CKB_INDEXER_NODE_URL = "http://localhost:8116";
private static final BigInteger UnitCKB = new BigInteger("100000000");
private static Api api;
private static CkbIndexerApi ckbIndexerApi;
private static List<String> SendPrivateKeys;
private static List<String> SendAddresses;
private static List<String> ReceiveAddresses;

static {
api = new Api(NODE_URL, false);
ckbIndexerApi = new CkbIndexerApi(CKB_INDEXER_NODE_URL, false);
SendPrivateKeys =
Arrays.asList(
"08730a367dfabcadb805d69e0e613558d5160eb8bab9d6e326980c2c46a05db2",
"d00c06bfd800d27397002dca6fb0993d5ba6399b4238b2f29ee9deb97593d2bc");
SendAddresses =
Arrays.asList(
"ckt1qyqxgp7za7dajm5wzjkye52asc8fxvvqy9eqlhp82g",
"ckt1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts8vyj37");
ReceiveAddresses =
Arrays.asList(
"ckt1qyqxvnycu7tdtyuejn3mmcnl4y09muxz8c3s2ewjd4",
"ckt1qyqtnz38fht9nvmrfdeunrhdtp29n0gagkps4duhek");
}

public static void main(String[] args) throws Exception {

System.out.println("Wait some time for ckb-indexer running");

List<Receiver> receivers =
Arrays.asList(
new Receiver(ReceiveAddresses.get(0), Utils.ckbToShannon(800)),
new Receiver(ReceiveAddresses.get(1), Utils.ckbToShannon(900)));

System.out.println(
"Before transferring, first sender's balance: "
+ getBalance(SendAddresses.get(0)).divide(UnitCKB).toString(10)
+ " CKB");

String hash = sendCapacity(receivers, SendAddresses.get(0));
System.out.println("Transaction hash: " + hash);

// waiting transaction into block, sometimes you should wait more seconds
Thread.sleep(30000);

System.out.println(
"After transferring, first sender's balance: "
+ getBalance(SendAddresses.get(0)).divide(UnitCKB).toString(10)
+ " CKB");
}

private static BigInteger getBalance(String address) throws IOException {
return new CollectUtils(ckbIndexerApi).getCapacityWithAddressByCkbIndexer(address);
}

private static String sendCapacity(List<Receiver> receivers, String changeAddress)
throws IOException {
List<ScriptGroupWithPrivateKeys> scriptGroupWithPrivateKeysList = new ArrayList<>();

TransactionBuilder txBuilder = new TransactionBuilder(api);
CollectUtils txUtils = new CollectUtils(ckbIndexerApi);

List<CellOutput> cellOutputs = txUtils.generateOutputs(receivers, changeAddress);
txBuilder.addOutputs(cellOutputs);

// You can get fee rate by rpc or set a simple number
BigInteger feeRate = BigInteger.valueOf(1024);

// initial_length = 2 * secp256k1_signature_byte.length
// collectInputsWithIndexer method uses indexer rpc to collect cells quickly
CollectResult collectResult =
txUtils.collectInputsWithCkbIndexer(
SendAddresses, txBuilder.buildTx(), feeRate, Sign.SIGN_LENGTH * 2, true);

// update change cell output capacity after collecting cells
cellOutputs.get(cellOutputs.size() - 1).capacity = collectResult.changeCapacity;
txBuilder.setOutputs(cellOutputs);

int startIndex = 0;
for (CellsWithAddress cellsWithAddress : collectResult.cellsWithAddresses) {
txBuilder.addInputs(cellsWithAddress.inputs);
for (int i = 0; i < cellsWithAddress.inputs.size(); i++) {
txBuilder.addWitness(i == 0 ? new Witness(Witness.SIGNATURE_PLACEHOLDER) : "0x");
}
if (cellsWithAddress.inputs.size() > 0) {
scriptGroupWithPrivateKeysList.add(
new ScriptGroupWithPrivateKeys(
new ScriptGroup(
NumberUtils.regionToList(startIndex, cellsWithAddress.inputs.size())),
Collections.singletonList(
SendPrivateKeys.get(SendAddresses.indexOf(cellsWithAddress.address)))));
startIndex += cellsWithAddress.inputs.size();
}
}

Secp256k1SighashAllBuilder signBuilder = new Secp256k1SighashAllBuilder(txBuilder.buildTx());

for (ScriptGroupWithPrivateKeys scriptGroupWithPrivateKeys : scriptGroupWithPrivateKeysList) {
signBuilder.sign(
scriptGroupWithPrivateKeys.scriptGroup, scriptGroupWithPrivateKeys.privateKeys.get(0));
}
Transaction tx = signBuilder.buildTx();
return api.sendTransaction(tx);
}
}
21 changes: 21 additions & 0 deletions example/src/main/java/org/nervos/ckb/indexer/CkbIndexerCell.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.nervos.ckb.indexer;

import com.google.gson.annotations.SerializedName;
import org.nervos.ckb.type.OutPoint;
import org.nervos.ckb.type.cell.CellOutput;

public class CkbIndexerCell {
@SerializedName("block_number")
public String blockNumber;

@SerializedName("out_point")
public OutPoint outPoint;

public CellOutput output;

@SerializedName("output_data")
public String outputData;

@SerializedName("tx_index")
public String txIndex;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.nervos.ckb.indexer;

import com.google.gson.annotations.SerializedName;
import java.util.List;

public class CkbIndexerCellResponse {
public List<CkbIndexerCell> objects;

@SerializedName("last_cursor")
public String lastCursor;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.nervos.ckb.indexer;

import com.google.gson.annotations.SerializedName;

public class CkbIndexerCellsCapacityResponse {
@SerializedName("block_hash")
public String blockHash;

@SerializedName("block_number")
public String blockNumber;

public String capacity;
}
21 changes: 21 additions & 0 deletions example/src/main/java/org/nervos/ckb/indexer/SearchKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.nervos.ckb.indexer;

import com.google.gson.annotations.SerializedName;
import org.nervos.ckb.type.Script;

public class SearchKey {
public Script script;

@SerializedName("script_type")
public String scriptType;

public SearchKey(Script script, String scriptType) {
this.script = script;
this.scriptType = scriptType;
}

public SearchKey(Script script) {
this.script = script;
this.scriptType = "lock";
}
}
46 changes: 46 additions & 0 deletions example/src/main/java/org/nervos/ckb/service/CkbIndexerApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.nervos.ckb.service;

import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import org.nervos.ckb.indexer.CkbIndexerCellResponse;
import org.nervos.ckb.indexer.CkbIndexerCellsCapacityResponse;
import org.nervos.ckb.indexer.SearchKey;
import org.nervos.ckb.utils.Numeric;

/** Copyright © 2020 Nervos Foundation. All rights reserved. */
public class CkbIndexerApi {

private RpcService rpcService;

public CkbIndexerApi(String nodeUrl) {
this(nodeUrl, false);
}

public CkbIndexerApi(String nodeUrl, boolean isDebug) {
rpcService = new RpcService(nodeUrl, isDebug);
}

public CkbIndexerCellResponse getCells(
SearchKey searchKey, String order, BigInteger limit, String afterCursor) throws IOException {
if ("0x".equals(afterCursor)) {
return rpcService.post(
"get_cells",
Arrays.asList(searchKey, order, Numeric.toHexStringWithPrefix(limit)),
CkbIndexerCellResponse.class);
} else {
return rpcService.post(
"get_cells",
Arrays.asList(searchKey, order, Numeric.toHexStringWithPrefix(limit), afterCursor),
CkbIndexerCellResponse.class);
}
}

public CkbIndexerCellsCapacityResponse getCellsCapacity(SearchKey searchKey) throws IOException {
return rpcService.post(
"get_cells_capacity",
Collections.singletonList(searchKey),
CkbIndexerCellsCapacityResponse.class);
}
}
Loading

0 comments on commit a8ce6d6

Please sign in to comment.