-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #274 from Concordium/smartContractSchema
Smart contract schema support
- Loading branch information
Showing
90 changed files
with
3,848 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
152 changes: 152 additions & 0 deletions
152
...k-examples/src/main/java/com/concordium/sdk/examples/contractexample/cis2nft/Cis2Nft.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
package com.concordium.sdk.examples.contractexample.cis2nft; | ||
|
||
import com.concordium.sdk.ClientV2; | ||
import com.concordium.sdk.Connection; | ||
import com.concordium.sdk.crypto.ed25519.ED25519SecretKey; | ||
import com.concordium.sdk.exceptions.ClientInitializationException; | ||
import com.concordium.sdk.requests.AccountQuery; | ||
import com.concordium.sdk.requests.BlockQuery; | ||
import com.concordium.sdk.responses.blockitemstatus.FinalizedBlockItem; | ||
import com.concordium.sdk.responses.modulelist.ModuleRef; | ||
import com.concordium.sdk.transactions.*; | ||
import com.concordium.sdk.transactions.smartcontracts.SchemaParameter; | ||
import com.concordium.sdk.types.AccountAddress; | ||
import com.concordium.sdk.types.ContractAddress; | ||
import com.concordium.sdk.types.Nonce; | ||
import com.concordium.sdk.types.UInt64; | ||
import lombok.var; | ||
import picocli.CommandLine; | ||
|
||
import java.io.IOException; | ||
import java.net.URL; | ||
import java.util.Optional; | ||
import java.util.concurrent.Callable; | ||
|
||
/** | ||
* Calls different methods on a <a href="https://github.com/Concordium/concordium-rust-smart-contracts/blob/main/examples/cis2-nft/src/lib.rs">cis2-nft smart contract</a> deployed on the chain. | ||
* See {@link Cis2NftParameters} for how to create and initialize custom smart contract parameters. | ||
* SENDER_ADDRESS, MODULE_REF, CONTRACT_ADDRESS and the key in SIGNER are dummy values and should be replaced | ||
*/ | ||
@CommandLine.Command(name = "Cis2Nft", mixinStandardHelpOptions = true) | ||
public class Cis2Nft implements Callable<Integer> { | ||
@CommandLine.Option( | ||
names = {"-m", "--method"}, | ||
required = true, | ||
description = "Name of method. Valid names are: ${COMPLETION-CANDIDATES}") | ||
private Cis2NftMethod methodName; | ||
|
||
@CommandLine.Option( | ||
names = {"--endpoint"}, | ||
description = "GRPC interface of the node.", | ||
defaultValue = "http://localhost:20002") | ||
private String endpoint; | ||
|
||
@CommandLine.Option( | ||
names = {"--timeout"}, | ||
description = "GRPC request timeout in milliseconds.", | ||
defaultValue = "100000") | ||
private int timeout; | ||
|
||
@CommandLine.Option( | ||
names = {"--wait"}, | ||
description = "How long to wait for transaction finalization.", | ||
defaultValue = "100000") | ||
private int wait; | ||
private static final String SENDER_ADDRESS = "3WZE6etUvVp1eyhEtTxqZrQaanTAZnZCHEmZmDyCbCwxnmQuPE"; // Dummy address | ||
private static final ModuleRef MODULE_REF = ModuleRef.from("247a7ac6efd2e46f72fd18741a6d1a0254ec14f95639df37079a576b2033873e"); // Dummy module ref | ||
private static final ContractAddress CONTRACT_ADDRESS = ContractAddress.from(1, 0); // Dummy contract address | ||
private static final Expiry EXPIRY = Expiry.createNew().addMinutes(5); | ||
private static final TransactionSigner SIGNER = TransactionSigner.from( | ||
SignerEntry.from(Index.from(0), Index.from(0), | ||
ED25519SecretKey.from("56f60de843790c308dac2d59a5eec9f6b1649513f827e5a13d7038accfe31784")) // Dummy key | ||
); | ||
|
||
@Override | ||
public Integer call() throws IOException, ClientInitializationException { | ||
var endpointUrl = new URL(this.endpoint); | ||
Connection connection = Connection.newBuilder() | ||
.host(endpointUrl.getHost()) | ||
.port(endpointUrl.getPort()) | ||
.timeout(timeout) | ||
.build(); | ||
var client = ClientV2.from(connection); | ||
Nonce nonce = client.getAccountInfo(BlockQuery.BEST, AccountQuery.from(AccountAddress.from(SENDER_ADDRESS))).getAccountNonce(); | ||
|
||
switch (this.methodName) { | ||
case INIT: | ||
handleInit(client, nonce); | ||
break; | ||
case MINT: | ||
SchemaParameter mintParams = Cis2NftParameters.generateMintParams(); | ||
handleMethod(client, nonce, mintParams); | ||
break; | ||
case TRANSFER: | ||
SchemaParameter transferParams = Cis2NftParameters.generateTransferParams(); | ||
handleMethod(client, nonce, transferParams); | ||
break; | ||
case UPDATE_OPERATOR: | ||
SchemaParameter updateOperatorParams = Cis2NftParameters.generateUpdateOperatorParams(); | ||
handleMethod(client, nonce, updateOperatorParams); | ||
break; | ||
case OPERATOR_OF: | ||
SchemaParameter operatorOfParams = Cis2NftParameters.generateOperatorOfParams(); | ||
handleMethod(client, nonce, operatorOfParams); | ||
break; | ||
case BALANCE_OF: | ||
SchemaParameter balanceOfParams = Cis2NftParameters.generateBalanceOfParams(); | ||
handleMethod(client, nonce, balanceOfParams); | ||
break; | ||
case TOKEN_METADATA: | ||
SchemaParameter tokenMetadataParams = Cis2NftParameters.generateTokenMetadataParams(); | ||
handleMethod(client, nonce, tokenMetadataParams); | ||
break; | ||
case SUPPORTS: | ||
SchemaParameter supportsParams = Cis2NftParameters.generateSupportsParameter(); | ||
handleMethod(client, nonce, supportsParams); | ||
break; | ||
case SET_IMPLEMENTORS: | ||
SchemaParameter setImplementorsParams = Cis2NftParameters.generateSetImplementorsParams(); | ||
handleMethod(client, nonce, setImplementorsParams); | ||
break; | ||
} | ||
return 0; | ||
} | ||
|
||
private void handleInit(ClientV2 client, Nonce nonce) { | ||
InitName initName = InitName.from("init_cis2_nft"); | ||
InitContractPayload payload = InitContractPayload.from(CCDAmount.fromMicro(0), MODULE_REF, initName, Parameter.EMPTY); | ||
InitContractTransaction initContractTransaction = TransactionFactory.newInitContract() | ||
.sender(AccountAddress.from(SENDER_ADDRESS)) | ||
.payload(payload) | ||
.expiry(EXPIRY) | ||
.nonce(AccountNonce.from(nonce)) | ||
.signer(SIGNER) | ||
.maxEnergyCost(UInt64.from(10000)) | ||
.build(); | ||
Hash txHash = client.sendTransaction(initContractTransaction); | ||
System.out.println("Submitted transaction for " + this.methodName + " with hash: " + txHash); | ||
Optional<FinalizedBlockItem> finalizedTransaction = client.waitUntilFinalized(txHash, wait); | ||
finalizedTransaction.ifPresent(finalizedBlockItem -> System.out.println("Transaction finalized in block with hash: " + finalizedBlockItem.getBlockHash())); | ||
} | ||
|
||
private void handleMethod(ClientV2 client, Nonce nonce, SchemaParameter parameter) { | ||
UpdateContract payload = UpdateContract.from(CONTRACT_ADDRESS, parameter); | ||
UpdateContractTransaction transaction = TransactionFactory.newUpdateContract() | ||
.sender(AccountAddress.from(SENDER_ADDRESS)) | ||
.payload(payload) | ||
.expiry(EXPIRY) | ||
.nonce(AccountNonce.from(nonce)) | ||
.signer(SIGNER) | ||
.maxEnergyCost(UInt64.from(10000)) | ||
.build(); | ||
Hash txHash = client.sendTransaction(transaction); | ||
System.out.println("Submitted transaction for " + this.methodName + " with hash: " + txHash); | ||
Optional<FinalizedBlockItem> finalizedTransaction = client.waitUntilFinalized(txHash, wait); | ||
finalizedTransaction.ifPresent(finalizedBlockItem -> System.out.println("Transaction finalized in block with hash: " + finalizedBlockItem.getBlockHash())); | ||
} | ||
|
||
public static void main(String[] args) { | ||
int exitCode = new CommandLine(new Cis2Nft()).execute(args); | ||
System.exit(exitCode); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
...ples/src/main/java/com/concordium/sdk/examples/contractexample/cis2nft/Cis2NftMethod.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.concordium.sdk.examples.contractexample.cis2nft; | ||
|
||
import com.concordium.sdk.examples.contractexample.parameters.*; | ||
|
||
/** | ||
* Represents the different possible methods able to be run by {@link Cis2Nft} representing a <a href="https://github.com/Concordium/concordium-rust-smart-contracts/blob/main/examples/cis2-nft/src/lib.rs">cis2-nft contract</a>. | ||
*/ | ||
public enum Cis2NftMethod { | ||
/** | ||
* The init method. | ||
*/ | ||
INIT, | ||
/** | ||
* The 'mint' method. Uses parameter {@link MintParams}. | ||
*/ | ||
MINT, | ||
/** | ||
* The 'transfer' method. Uses parameter {@link NftTransferParam}. | ||
*/ | ||
TRANSFER, | ||
/** | ||
* The 'updateOperator' method. Uses parameter {@link UpdateOperator}. | ||
*/ | ||
UPDATE_OPERATOR, | ||
/** | ||
* The 'operatorOf' of method. Uses parameter {@link OperatorOfQueryParams}. | ||
*/ | ||
OPERATOR_OF, | ||
/** | ||
* The 'balanceOf' method. Uses parameter {@link NftBalanceOfQueryParams}. | ||
*/ | ||
BALANCE_OF, | ||
/** | ||
* The 'tokenMetadata' method. Uses parameter {@link NftTokenMetaDataQueryParams}. | ||
*/ | ||
TOKEN_METADATA, | ||
/** | ||
* The 'supports' method. Uses parameter {@link SupportsQueryParams}. | ||
*/ | ||
SUPPORTS, | ||
/** | ||
* The 'setImplementors method. Uses parameter {@link SetImplementorsParams}. | ||
*/ | ||
SET_IMPLEMENTORS, | ||
} |
183 changes: 183 additions & 0 deletions
183
.../src/main/java/com/concordium/sdk/examples/contractexample/cis2nft/Cis2NftParameters.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
package com.concordium.sdk.examples.contractexample.cis2nft; | ||
|
||
import com.concordium.sdk.examples.contractexample.parameters.*; | ||
import com.concordium.sdk.transactions.ReceiveName; | ||
import com.concordium.sdk.transactions.smartcontracts.Schema; | ||
import com.concordium.sdk.transactions.smartcontracts.SchemaParameter; | ||
import com.concordium.sdk.types.*; | ||
import lombok.SneakyThrows; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Paths; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
/** | ||
* Helper class for creating and initializing parameters being used in {@link Cis2Nft} representing a <a href="https://github.com/Concordium/concordium-rust-smart-contracts/blob/main/examples/cis2-nft/src/lib.rs">cis2-nft contract</a>. | ||
* All values are dummy values and should be replaced to get valid results. | ||
*/ | ||
public class Cis2NftParameters { | ||
private static final AccountAddress ACCOUNT_ADDRESS = AccountAddress.from("3XSLuJcXg6xEua6iBPnWacc3iWh93yEDMCqX8FbE3RDSbEnT9P"); | ||
private static final ContractAddress CONTRACT_ADDRESS_1 = ContractAddress.from(1, 0); | ||
private static final ContractAddress CONTRACT_ADDRESS_2 = ContractAddress.from(2, 0); | ||
private static final String CIS_2_NFT_CONTRACT_NAME = "cis2_nft"; | ||
|
||
private static final String SCHEMA_PATH = "./src/main/java/com/concordium/sdk/examples/contractexample/cis2nft/cis2-nft.schema.bin"; | ||
|
||
private static final Schema SCHEMA; | ||
|
||
static { | ||
try { | ||
SCHEMA = Schema.from(Files.readAllBytes(Paths.get(SCHEMA_PATH))); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
/** | ||
* Generates and initializes {@link MintParams} for the 'mint' method of a cis2-nft contract. | ||
* | ||
* @return initialized {@link MintParams}. | ||
*/ | ||
@SneakyThrows | ||
public static SchemaParameter generateMintParams() { | ||
ReceiveName mintParamsReceiveName = ReceiveName.from(CIS_2_NFT_CONTRACT_NAME, "mint"); | ||
List<TokenIdU32> tokens = new ArrayList<>(); | ||
tokens.add(TokenIdU32.from(2)); | ||
tokens.add(TokenIdU32.from(22)); | ||
tokens.add(TokenIdU32.from(2132)); | ||
SchemaParameter mintParameter = new MintParams(SCHEMA, mintParamsReceiveName, ACCOUNT_ADDRESS, tokens); | ||
mintParameter.initialize(true); | ||
return mintParameter; | ||
} | ||
|
||
/** | ||
* Generates and initializes {@link NftTransferParam} for the 'transfer' method of a cis2-nft contract. | ||
* | ||
* @return initialized {@link NftTransferParam}. | ||
*/ | ||
@SneakyThrows | ||
public static SchemaParameter generateTransferParams() { | ||
ReceiveName nftTransferReceiveName = ReceiveName.from(CIS_2_NFT_CONTRACT_NAME, "transfer"); | ||
TokenIdU32 tokenId = TokenIdU32.from(12); | ||
TokenAmountU8 amount = TokenAmountU8.from(1); | ||
AbstractAddress from = CONTRACT_ADDRESS_1; | ||
Receiver to = new Receiver(CONTRACT_ADDRESS_2, "mint"); | ||
byte[] data = new byte[]{123, -23}; | ||
NftTransfer transfer = new NftTransfer(tokenId, amount, from, to, data); | ||
List<NftTransfer> transfers = new ArrayList<>(); | ||
transfers.add(transfer); | ||
SchemaParameter transferParameter = new NftTransferParam(SCHEMA, nftTransferReceiveName, transfers); | ||
transferParameter.initialize(true); | ||
return transferParameter; | ||
} | ||
|
||
/** | ||
* Generates and initializes {@link UpdateOperatorParams} for the 'updateOperator' method of a cis2-nft contract. | ||
* | ||
* @return initialized {@link UpdateOperatorParams}. | ||
*/ | ||
@SneakyThrows | ||
public static SchemaParameter generateUpdateOperatorParams() { | ||
ReceiveName updateOperatorReceiveName = ReceiveName.from(CIS_2_NFT_CONTRACT_NAME, "updateOperator"); | ||
UpdateOperator update1 = new UpdateOperator(UpdateOperator.OperatorUpdate.ADD, ACCOUNT_ADDRESS); | ||
UpdateOperator update2 = new UpdateOperator(UpdateOperator.OperatorUpdate.REMOVE, CONTRACT_ADDRESS_1); | ||
List<UpdateOperator> updateOperatorList = new ArrayList<>(); | ||
updateOperatorList.add(update1); | ||
updateOperatorList.add(update2); | ||
SchemaParameter updateOperatorsParams = new UpdateOperatorParams(SCHEMA, updateOperatorReceiveName, updateOperatorList); | ||
updateOperatorsParams.initialize(true); | ||
return updateOperatorsParams; | ||
} | ||
|
||
/** | ||
* Generates and initializes {@link OperatorOfQueryParams} for the 'operatorOf' method of a cis2-nft contract. | ||
* | ||
* @return initialized {@link OperatorOfQueryParams}. | ||
*/ | ||
@SneakyThrows | ||
public static SchemaParameter generateOperatorOfParams() { | ||
ReceiveName operatorOfReceiveName = ReceiveName.from(CIS_2_NFT_CONTRACT_NAME, "operatorOf"); | ||
OperatorOfQuery operatorOfQuery1 = new OperatorOfQuery(ACCOUNT_ADDRESS, CONTRACT_ADDRESS_1); | ||
OperatorOfQuery operatorOfQuery2 = new OperatorOfQuery(CONTRACT_ADDRESS_1, CONTRACT_ADDRESS_2); | ||
List<OperatorOfQuery> operatorOfQueries = new ArrayList<>(); | ||
operatorOfQueries.add(operatorOfQuery1); | ||
operatorOfQueries.add(operatorOfQuery2); | ||
SchemaParameter operatorOfQueryParams = new OperatorOfQueryParams(SCHEMA, operatorOfReceiveName, operatorOfQueries); | ||
operatorOfQueryParams.initialize(true); | ||
return operatorOfQueryParams; | ||
} | ||
|
||
/** | ||
* Generates and initializes {@link NftBalanceOfQueryParams} for the 'balanceOf' method of a cis2-nft contract. | ||
* | ||
* @return initialized {@link NftBalanceOfQueryParams}. | ||
*/ | ||
@SneakyThrows | ||
public static SchemaParameter generateBalanceOfParams() { | ||
ReceiveName balanceOfReceiveName = ReceiveName.from(CIS_2_NFT_CONTRACT_NAME, "balanceOf"); | ||
NftBalanceOfQuery balanceOfQuery1 = new NftBalanceOfQuery(TokenIdU32.from(22222), ACCOUNT_ADDRESS); | ||
NftBalanceOfQuery balanceOfQuery2 = new NftBalanceOfQuery(TokenIdU32.from(42), CONTRACT_ADDRESS_1); | ||
List<NftBalanceOfQuery> balanceOfQueries = new ArrayList<>(); | ||
balanceOfQueries.add(balanceOfQuery1); | ||
balanceOfQueries.add(balanceOfQuery2); | ||
SchemaParameter contractBalanceOfQueryParams = new NftBalanceOfQueryParams(SCHEMA, balanceOfReceiveName, balanceOfQueries); | ||
contractBalanceOfQueryParams.initialize(true); | ||
return contractBalanceOfQueryParams; | ||
} | ||
|
||
/** | ||
* Generates and initializes {@link NftTokenMetaDataQueryParams} for the 'tokenMetadata' method of a cis2-nft contract. | ||
* | ||
* @return initialized {@link NftTokenMetaDataQueryParams}. | ||
*/ | ||
@SneakyThrows | ||
public static SchemaParameter generateTokenMetadataParams() { | ||
ReceiveName tokenMetadataReceiveName = ReceiveName.from(CIS_2_NFT_CONTRACT_NAME, "tokenMetadata"); | ||
TokenIdU32 token1 = TokenIdU32.from(21); | ||
TokenIdU32 token2 = TokenIdU32.from(22); | ||
List<TokenIdU32> tokensForMetadataQuery = new ArrayList<>(); | ||
tokensForMetadataQuery.add(token1); | ||
tokensForMetadataQuery.add(token2); | ||
SchemaParameter nftMetaDataQuery = new NftTokenMetaDataQueryParams(SCHEMA, tokenMetadataReceiveName, tokensForMetadataQuery); | ||
nftMetaDataQuery.initialize(true); | ||
return nftMetaDataQuery; | ||
} | ||
|
||
/** | ||
* Generates and initializes {@link SupportsQueryParams} for the 'supports' method of a cis2-nft contract. | ||
* | ||
* @return initialized {@link SupportsQueryParams}. | ||
*/ | ||
@SneakyThrows | ||
public static SchemaParameter generateSupportsParameter() { | ||
ReceiveName supportsReceiveName = ReceiveName.from(CIS_2_NFT_CONTRACT_NAME, "supports"); | ||
String standardIdentifier1 = "identifier1"; | ||
String standardIdentifier2 = "identifier2"; | ||
List<String> identifiers = new ArrayList<>(); | ||
identifiers.add(standardIdentifier1); | ||
identifiers.add(standardIdentifier2); | ||
SchemaParameter supportsQueryParams = new SupportsQueryParams(SCHEMA, supportsReceiveName, identifiers); | ||
supportsQueryParams.initialize(true); | ||
return supportsQueryParams; | ||
} | ||
|
||
/** | ||
* Generates and initializes {@link SetImplementorsParams} for the 'setImplementors' method of a cis2-nft contract. | ||
* | ||
* @return initialized {@link SetImplementorsParams}. | ||
*/ | ||
@SneakyThrows | ||
public static SchemaParameter generateSetImplementorsParams() { | ||
ReceiveName setImplementorsReceiveName = ReceiveName.from(CIS_2_NFT_CONTRACT_NAME, "setImplementors"); | ||
List<ContractAddress> implementors = new ArrayList<>(); | ||
String identifier = "IdentifierID"; | ||
implementors.add(CONTRACT_ADDRESS_1); | ||
implementors.add(CONTRACT_ADDRESS_2); | ||
SchemaParameter setImplementorsParams = new SetImplementorsParams(SCHEMA, setImplementorsReceiveName, identifier, implementors); | ||
setImplementorsParams.initialize(); | ||
return setImplementorsParams; | ||
} | ||
|
||
} |
Binary file added
BIN
+2.91 KB
...les/src/main/java/com/concordium/sdk/examples/contractexample/cis2nft/cis2-nft.schema.bin
Binary file not shown.
Oops, something went wrong.