Skip to content

Commit

Permalink
Merge pull request #321 from nervosnetwork/rc/v0.32.0
Browse files Browse the repository at this point in the history
Rc/v0.32.0
  • Loading branch information
duanyytop authored May 26, 2020
2 parents 324f712 + 1a995e8 commit 1248a8f
Show file tree
Hide file tree
Showing 11 changed files with 625 additions and 22 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [v0.32.0](https://github.com/nervosnetwork/ckb-sdk-java/compare/v0.31.0...v0.32.0) (2020-5-26)

### Feature

* Add Simple UDT example ([18a15f5](https://github.com/nervosnetwork/ckb-sdk-java/commit/18a15f5c4f9d90a62a4b5368a46a94ca89d912e6))


# [v0.31.0](https://github.com/nervosnetwork/ckb-sdk-java/compare/v0.30.0...v0.31.0) (2020-4-17)

### Refactor
Expand Down
8 changes: 4 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ buildscript {
ext.bouncycastleVersion = '1.65'
ext.rxjavaVersion = '2.2.19'
ext.gsonVersion = '2.8.6'
ext.okhttpVersion = '4.5.0'
ext.loggingOkhttpVersion = '4.5.0'
ext.okhttpVersion = '4.7.1'
ext.loggingOkhttpVersion = '4.7.1'
ext.slf4jVersion = '1.7.30'
ext.guavaVersion = '29.0-jre'

Expand Down Expand Up @@ -43,7 +43,7 @@ allprojects {
targetCompatibility = 1.8

group 'org.nervos.ckb'
version '0.31.0'
version '0.32.0'

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.31.0'
version '0.32.0'
from components.java
}
}
Expand Down
4 changes: 2 additions & 2 deletions example/src/main/java/org/nervos/ckb/NervosDaoExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ private static Transaction generateDepositingToDaoTx(BigInteger capacity) throws
// You can get fee rate by rpc or set a simple number
// BigInteger feeRate = Numeric.toBigInt(api.estimateFeeRate("5").feeRate);
BigInteger feeRate = BigInteger.valueOf(1024);
CollectUtils collectUtils = new CollectUtils(api, true);
CollectUtils collectUtils = new CollectUtils(api);
CollectResult collectResult =
collectUtils.collectInputs(
Collections.singletonList(DaoTestAddress),
Expand Down Expand Up @@ -177,7 +177,7 @@ private static Transaction generateWithdrawingFromDaoTx(OutPoint depositOutPoint
// You can get fee rate by rpc or set a simple number
// BigInteger feeRate = Numeric.toBigInt(api.estimateFeeRate("5").feeRate);
BigInteger feeRate = BigInteger.valueOf(1024);
CollectUtils collectUtils = new CollectUtils(api, true);
CollectUtils collectUtils = new CollectUtils(api);
CollectResult collectResult =
collectUtils.collectInputs(
Collections.singletonList(DaoTestAddress),
Expand Down
253 changes: 253 additions & 0 deletions example/src/main/java/org/nervos/ckb/SUDTExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
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.transaction.*;
import org.nervos.ckb.type.OutPoint;
import org.nervos.ckb.type.Script;
import org.nervos.ckb.type.Witness;
import org.nervos.ckb.type.cell.CellDep;
import org.nervos.ckb.type.cell.CellOutput;
import org.nervos.ckb.type.fixed.UInt128;
import org.nervos.ckb.udt.UDTCellCollector;
import org.nervos.ckb.udt.UDTCollectResult;
import org.nervos.ckb.utils.Numeric;
import org.nervos.ckb.utils.Utils;

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

private static final BigInteger UnitCKB = new BigInteger("100000000");
private static final String SUDT_CODE_HASH =
"0x48dbf59b4c7ee1547238021b4869bceedf4eea6b43772e5d66ef8865b6ae7212";
private static final String SUDT_OUT_POINT_TX_HASH =
"0xc1b2ae129fad7465aaa9acc9785f842ba3e6e8b8051d899defa89f5508a77958";
private static final String OUTPUTS_DATE_PLACEHOLDER = "00000000000000000000000000000000";
private static final BigInteger SUDT_MIN_CELL_CAPACITY = Utils.ckbToShannon(142);
private static final BigInteger SUDT_ISSUE_CELL_CAPACITY = Utils.ckbToShannon(1000);
private static final String ReceiveAddress = "ckt1qyqvsv5240xeh85wvnau2eky8pwrhh4jr8ts8vyj37";
private static final String TestPrivateKey =
"e79f3207ea4980b7fed79956d5934249ceac4751a4fae01a0f7c4a96884bc4e3";
private static final String TestAddress = "ckt1qyqrdsefa43s6m882pcj53m4gdnj4k440axqswmu83";

private static final String NODE_URL = "http://localhost:8114";
private static Api api;

static {
api = new Api(NODE_URL, false);
}

public static void main(String[] args) throws Exception {
System.out.println("Tip block number: " + api.getTipBlockNumber());
Script udtType =
new Script(SUDT_CODE_HASH, LockUtils.generateLockHashWithAddress(TestAddress), Script.DATA);
String hash = issue(BigInteger.valueOf(10000000000L), udtType);
System.out.println("UDT issue hash: " + hash);

Thread.sleep(30000);

String balance = getUdtBalance(TestAddress, udtType.computeHash());
System.out.println("Balance: " + balance);

String transferHash = transfer(BigInteger.valueOf(100000L), udtType);
System.out.println("UDT transfer hash: " + transferHash);

Thread.sleep(30000);

String burnHash = burn(BigInteger.valueOf(1000L), udtType);
System.out.println("UDT burn hash: " + burnHash);
}

private static String issue(BigInteger udtAmount, Script udtType) throws IOException {
List<ScriptGroupWithPrivateKeys> scriptGroupWithPrivateKeysList = new ArrayList<>();

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

Receiver receiver = new Receiver(TestAddress, SUDT_ISSUE_CELL_CAPACITY);
List<CellOutput> cellOutputs =
txUtils.generateOutputs(Collections.singletonList(receiver), TestAddress);

cellOutputs.get(0).type = udtType;
List<String> cellOutputsData =
Arrays.asList(Numeric.toHexString(new UInt128(udtAmount).toBytes()), "0x");

txBuilder.addOutputs(cellOutputs);
txBuilder.setOutputsData(cellOutputsData);
txBuilder.addCellDep(new CellDep(new OutPoint(SUDT_OUT_POINT_TX_HASH, "0x0"), CellDep.CODE));

// You can get fee rate by rpc or set a simple number
// BigInteger feeRate = Numeric.toBigInt(api.estimateFeeRate("5").feeRate);
BigInteger feeRate = BigInteger.valueOf(1024);

// initial_length = 2 * secp256k1_signature_byte.length
CollectResult collectResult =
txUtils.collectInputs(
Collections.singletonList(TestAddress),
txBuilder.buildTx(),
feeRate,
Sign.SIGN_LENGTH * 2);

// update change 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");
}
scriptGroupWithPrivateKeysList.add(
new ScriptGroupWithPrivateKeys(
new ScriptGroup(NumberUtils.regionToList(startIndex, cellsWithAddress.inputs.size())),
Collections.singletonList(TestPrivateKey)));
}

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

for (ScriptGroupWithPrivateKeys scriptGroupWithPrivateKeys : scriptGroupWithPrivateKeysList) {
signBuilder.sign(
scriptGroupWithPrivateKeys.scriptGroup, scriptGroupWithPrivateKeys.privateKeys.get(0));
}
return api.sendTransaction(signBuilder.buildTx());
}

private static String getUdtBalance(String address, String typeHash) throws IOException {
return new UDTCellCollector(api).getUdtBalanceWithAddress(address, typeHash).toString(10);
}

private static String transfer(BigInteger udtAmount, Script udtType) throws IOException {
List<ScriptGroupWithPrivateKeys> scriptGroupWithPrivateKeysList = new ArrayList<>();

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

Receiver receiver = new Receiver(ReceiveAddress, SUDT_MIN_CELL_CAPACITY);
List<CellOutput> cellOutputs =
txUtils.generateOutputs(Collections.singletonList(receiver), TestAddress);

for (CellOutput output : cellOutputs) {
output.type = udtType;
}
txBuilder.addOutputs(cellOutputs);

List<String> cellOutputsData =
Arrays.asList(
Numeric.toHexString(new UInt128(udtAmount).toBytes()),
Numeric.toHexString(new UInt128(OUTPUTS_DATE_PLACEHOLDER).toBytes()));
txBuilder.setOutputsData(cellOutputsData);

txBuilder.addCellDep(new CellDep(new OutPoint(SUDT_OUT_POINT_TX_HASH, "0x0"), CellDep.CODE));

// You can get fee rate by rpc or set a simple number
// BigInteger feeRate = Numeric.toBigInt(api.estimateFeeRate("5").feeRate);
BigInteger feeRate = BigInteger.valueOf(1024);

// initial_length = 2 * secp256k1_signature_byte.length
UDTCollectResult result =
new UDTCellCollector(api)
.collectInputs(
Collections.singletonList(TestAddress),
txBuilder.buildTx(),
feeRate,
Sign.SIGN_LENGTH * 2,
udtType.computeHash(),
udtAmount);

// update change output capacity after collecting cells
cellOutputs.get(1).capacity = result.changeCapacity;

txBuilder.setOutputs(cellOutputs);

cellOutputsData.set(1, Numeric.toHexString(new UInt128(result.changeUdtAmount).toBytes()));
txBuilder.setOutputsData(cellOutputsData);

int startIndex = 0;
for (CellsWithAddress cellsWithAddress : result.cellsWithAddresses) {
txBuilder.addInputs(cellsWithAddress.inputs);
for (int i = 0; i < cellsWithAddress.inputs.size(); i++) {
txBuilder.addWitness(i == 0 ? new Witness(Witness.SIGNATURE_PLACEHOLDER) : "0x");
}
scriptGroupWithPrivateKeysList.add(
new ScriptGroupWithPrivateKeys(
new ScriptGroup(NumberUtils.regionToList(startIndex, cellsWithAddress.inputs.size())),
Collections.singletonList(TestPrivateKey)));
}

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

for (ScriptGroupWithPrivateKeys scriptGroupWithPrivateKeys : scriptGroupWithPrivateKeysList) {
signBuilder.sign(
scriptGroupWithPrivateKeys.scriptGroup, scriptGroupWithPrivateKeys.privateKeys.get(0));
}
return api.sendTransaction(signBuilder.buildTx());
}

private static String burn(BigInteger udtAmount, Script udtType) throws IOException {
List<ScriptGroupWithPrivateKeys> scriptGroupWithPrivateKeysList = new ArrayList<>();

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

Receiver receiver = new Receiver(TestAddress, SUDT_MIN_CELL_CAPACITY);
List<CellOutput> cellOutputs =
txUtils.generateOutputs(Collections.singletonList(receiver), TestAddress);

cellOutputs.get(1).type = udtType;
txBuilder.addOutputs(cellOutputs);

List<String> cellOutputsData =
Arrays.asList("0x", Numeric.toHexString(new UInt128(OUTPUTS_DATE_PLACEHOLDER).toBytes()));
txBuilder.setOutputsData(cellOutputsData);

txBuilder.addCellDep(new CellDep(new OutPoint(SUDT_OUT_POINT_TX_HASH, "0x0"), CellDep.CODE));

// You can get fee rate by rpc or set a simple number
// BigInteger feeRate = Numeric.toBigInt(api.estimateFeeRate("5").feeRate);
BigInteger feeRate = BigInteger.valueOf(1024);

// initial_length = 2 * secp256k1_signature_byte.length
UDTCollectResult result =
new UDTCellCollector(api)
.collectInputs(
Collections.singletonList(TestAddress),
txBuilder.buildTx(),
feeRate,
Sign.SIGN_LENGTH * 2,
udtType.computeHash(),
udtAmount);

// update change output capacity after collecting cells
cellOutputs.get(1).capacity = result.changeCapacity;
txBuilder.setOutputs(cellOutputs);

cellOutputsData.set(1, Numeric.toHexString(new UInt128(result.changeUdtAmount).toBytes()));
txBuilder.setOutputsData(cellOutputsData);

int startIndex = 0;
for (CellsWithAddress cellsWithAddress : result.cellsWithAddresses) {
txBuilder.addInputs(cellsWithAddress.inputs);
for (int i = 0; i < cellsWithAddress.inputs.size(); i++) {
txBuilder.addWitness(i == 0 ? new Witness(Witness.SIGNATURE_PLACEHOLDER) : "0x");
}
scriptGroupWithPrivateKeysList.add(
new ScriptGroupWithPrivateKeys(
new ScriptGroup(NumberUtils.regionToList(startIndex, cellsWithAddress.inputs.size())),
Collections.singletonList(TestPrivateKey)));
}
Secp256k1SighashAllBuilder signBuilder = new Secp256k1SighashAllBuilder(txBuilder.buildTx());

for (ScriptGroupWithPrivateKeys scriptGroupWithPrivateKeys : scriptGroupWithPrivateKeysList) {
signBuilder.sign(
scriptGroupWithPrivateKeys.scriptGroup, scriptGroupWithPrivateKeys.privateKeys.get(0));
}
return api.sendTransaction(signBuilder.buildTx());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class CellBlockIterator implements Iterator<TransactionInput> {
this.fromBlockNumber = fromBlockNumber;

toBlockNumber = 0;

addressIndex = 0;
inputIndex = 0;

Expand All @@ -45,14 +46,10 @@ public class CellBlockIterator implements Iterator<TransactionInput> {
}
}

CellBlockIterator(Api api, List<String> addresses, boolean skipDataAndType) {
CellBlockIterator(Api api, List<String> addresses, boolean skipDataAndType, String typeHash) {
this(api, addresses, skipDataAndType, 0);
}

CellBlockIterator(Api api, List<String> addresses) {
this(api, addresses, true);
}

@Override
public boolean hasNext() {
return transactionInputs.size() > 0
Expand Down
Loading

0 comments on commit 1248a8f

Please sign in to comment.