A blockchain project led by VISA Only the edition called Chain Core Developer Edition is open sourced. Please refer to the article about the construction procedure up to the construction of the Chain environment. Chain environment construction
Please refer to the sample code in the document on the official page. https://chain.com/docs/core/get-started/introduction
Basically, if you look at the sample code, Javadoc, and SDK source code, you should know what to do.
Contracts etc. have not been implemented yet.
You can also check the executed transaction and the created account information on the dashboard that you can see by accessing the 1999 port of the server running Chain with a browser.
Broadly speaking, there are execution of search queries and transaction execution such as remittance. An authentication key is not required to execute a query, but an authentication key is required to execute an API that generates transactions such as withdrawals.
You can also see the internal ID etc. in Chain, Most of them are created by defining alias (alias) in currency, account, etc. Execution of queries and transactions is also executed using alias.
Make a note of the URL, port, and access key of the server running Chain.
public static final String TARGET_URL = "http://XX.XXX.XX.XXX:1999/";
public static final String TOKEN = "client:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
public static final String KEY_ALIAS = "test";
First, generate a Client class to connect to the server.
Client client = new Client(TARGET_URL,TOKEN);
When executing a search query, only Client is required, but when executing a transaction, the following authentication key must be set.
MockHsm.Key key = null;
MockHsm.Key.Items keys = new MockHsm.Key.QueryBuilder().addAlias(ApiSettings.KEY_ALIAS).execute(client);
if (keys.hasNext()){
key = keys.next();
}else{
key = MockHsm.Key.create(client,ApiSettings.KEY_ALIAS);
}
HsmSigner.addKey(key, MockHsm.getSignerClient(client));
If the alias specified when creating this authentication key is different, an authentication error will occur and remittance will not be possible. The Key used to create the remittance account must also be used to authenticate the remittance transaction.
MockHsm.Key key = MockHsm.Key.create(client);
If you create a Key without specifying an alias like this, an unlimited number of anonymous Keys will be created, so when creating it, specify an alias as shown below and create it with a specific key.
MockHsm.Key key = MockHsm.Key.create(client,ApiSettings.KEY_ALIAS);
This allows the created key to be retrieved by query and reused. On the contrary, if you do not specify alias, you will not be able to explicitly specify the key required for authentication of that account when executing a transaction. After that, account creation, asset (currency) definition, remittance, etc. are executed.
It's just for reference, but if you use the sample on the official page as it is, you will suffer from errors in handling authentication.
@Service
public class AccountService extends BaseService {
private static final Logger LOGGER = LoggerFactory.getLogger(AccountService.class.getName());
public String create(String account) throws ChainException{
Client client = createClient();
MockHsm.Key key = createKey(client);
HsmSigner.addKey(key, MockHsm.getSignerClient(client));
Account.Items accounts = new Account.QueryBuilder()
.setFilter("alias=$1")
.addFilterParameter(account)
.execute(client);
Account created = null;
if (accounts.hasNext()){
created = accounts.next();
LOGGER.info("account is exists.");
}else{
created = new Account.Builder()
.setAlias(account)
.addRootXpub(key.xpub)
.setQuorum(1)
.create(client);
LOGGER.info("account created.");
}
return created.alias;
}
}
Here, BaseService is as follows.
@Service
public class BaseService {
/**
*Get a connection client
* @return client
* @throws ChainException
*/
protected Client createClient() throws ChainException{
return new Client(ApiSettings.TARGET_URL,ApiSettings.TOKEN);
}
/**
*Get common authentication key
* @param client
* @return key
* @throws ChainException
*/
protected MockHsm.Key createKey(Client client) throws ChainException{
MockHsm.Key key = null;
MockHsm.Key.Items keys = new MockHsm.Key.QueryBuilder().addAlias(ApiSettings.KEY_ALIAS).execute(client);
if (keys.hasNext()){
key = keys.next();
}else{
key = MockHsm.Key.create(client,ApiSettings.KEY_ALIAS);
}
return key;
}
}
First, I'm using QueryBuilder to search for an account.
Account.Items accounts = new Account.QueryBuilder()
.setFilter("alias=$1")
.addFilterParameter(account)
.execute(client);
All major classes such as Account, Asset, Balance and MockHsm.Key have ** QueryBuilder () ** methods. You can search in a similar way.
Specify the search condition as a character string in ** setFilter ("condition") **. The conditions that can be specified here are described on the API Object page of the official documentation reference. https://chain.com/docs/core/reference/api-objects
In the next ** addFilterParameter (account) **, specify the character string to be embedded in ** \ $ 1, $ 2 ** specified by setFilter. Here, the account name character string (alias) passed as an argument is specified. After setting filter, execute with execute.
The query is described on the following page. https://chain.com/docs/core/build-applications/queries
The result will be returned by iterator such as Account.Items and Balance.Items.
if (accounts.hasNext()){
created = accounts.next();
I have obtained it at.
This is, for example
while (balances.hasNext()) {
Balance b = balances.next();
LOGGER.info("balance of " + b.sumBy.get("asset_alias") + ": " + b.amount);
}
As soon as you turn it with while,
assets.forEachRemaining(s -> {
assetList.add(new AssetDto(s.id,s.alias));
});
You can turn it with lambda like.
Finally, if there are no search results, a new account is created.
created = new Account.Builder()
.setAlias(account)
.addRootXpub(key.xpub)
.setQuorum(1)
.create(client);
LOGGER.info("account created.");
The MockHsm.Key used during this process will be the Key created in advance, but the same Key must be used to execute transactions related to this account. It should be created for each account, but since management is complicated, a common key (alias) is used here.
A transaction is being executed here. At the same time as the currency is generated, the currency is passed to the specified account. Input and output are always a set.
Define the currency in the ** Issue ** action and The ** ControlWithAccount ** action is passing the generated currency to the specified account.
@Service
public class IssueService extends BaseService {
private static final Logger LOGGER = LoggerFactory.getLogger(IssueService.class.getName());
public void issue(String assetName,String issueAccount,Long amount) throws ChainException{
Client client = createClient();
MockHsm.Key key = createKey(client);
HsmSigner.addKey(key, MockHsm.getSignerClient(client));
//Generate if the currency of assetName is not defined.
if (!isExistAsset(assetName,client)){
new Asset.Builder()
.setAlias(assetName)
.addRootXpub(key.xpub)
.setQuorum(1)
.create(client);
}
//Currency definition transaction.
//The currency of assetName is distributed to issueAccount by amount from Issue action to ControlWithAccount action.
Transaction.Template issuanceToProgram = new Transaction.Builder()
.addAction(new Transaction.Action.Issue()
.setAssetAlias(assetName)
.setAmount(amount)
).addAction(new Transaction.Action.ControlWithAccount()
.setAccountAlias(issueAccount)
.setAssetAlias(assetName)
.setAmount(amount)
).build(client);
//Transaction signing and execution
Transaction.Template signedIssuanceToProgram = HsmSigner.sign(issuanceToProgram);
Transaction.submit(client, signedIssuanceToProgram);
}
private boolean isExistAsset(String assetName,Client client) throws ChainException {
Asset.Items assets = new Asset.QueryBuilder()
.setFilter("alias=$1")
.addFilterParameter(assetName)
.execute(client);
if (assets.hasNext()){
return true;
}
return false;
}
}
Written like any other query.
@Service
public class AssetQueryService extends BaseService {
public List<AssetDto> getAssetList(String assetName) throws ChainException {
Client client = createClient();
Asset.Items assets = new Asset.QueryBuilder()
.setFilter("alias=$1")
.addFilterParameter(assetName)
.execute(client);
List<AssetDto> assetList = new ArrayList<>();
assets.forEachRemaining(s -> {
assetList.add(new AssetDto(s.id,s.alias));
});
return assetList;
}
}
This is also written in the same way except that the Balance class is used. The following example uses two search parameters.
@Service
public class BalanceService extends BaseService {
private static final Logger LOGGER = LoggerFactory
.getLogger(BalanceService.class.getName());
public ResponseBalanceDto getBalance(String assetName, String account)
throws ChainException {
Client client = createClient();
Balance.Items balances = new Balance.QueryBuilder()
.setFilter("account_alias=$1 AND asset_alias=$2")
.addFilterParameter(account)
.addFilterParameter(assetName)
.execute(client);
Balance balance = null;
ResponseBalanceDto responseDto = new ResponseBalanceDto();
if (balances.hasNext()){
balance = balances.next();
responseDto.setBalance(balance.amount);
LOGGER.info("account:{} asset:{} amount:{} ",account,assetName,balance.amount);
}
return responseDto;
}
}
With the ** SpendFromAccount ** action, withdraw currency from the sender and The ** ControlWithAccount ** action is passing currency to the recipient. Be careful of Key etc. because the transaction is not executed only by alias.
@Service
public class TransferService extends BaseService {
private static final Logger LOGGER = LoggerFactory.getLogger(TransferService.class.getName());
/**
*Remittance execution
* @param from Account Remittance source account
* @param to Account Remittance destination account
* @param assetName Currency name
* @param amount amount
* @throws ChainException
*/
public void transfer(String fromAccount, String toAccount,
String assetName, Long amount) throws ChainException {
Client client = createClient();
MockHsm.Key key = createKey(client);
HsmSigner.addKey(key, MockHsm.getSignerClient(client));
Transaction.Template transfertran = new Transaction.Builder()
.addAction(
new Transaction.Action.SpendFromAccount()
.setAccountAlias(fromAccount)
.setAssetAlias(assetName).setAmount(amount))
.addAction(
new Transaction.Action.ControlWithAccount()
.setAccountAlias(toAccount)
.setAssetAlias(assetName).setAmount(amount))
.build(client);
Transaction.Template signedTransfertran = HsmSigner.sign(transfertran);
Transaction.submit(client, signedTransfertran);
}
}
key Chain,blockchain,API
Recommended Posts