starknet-jvm
Starknet-jvm is a library allowing for easy interaction with the Starknet JSON-RPC nodes, including querying starknet state, executing transactions and deploying contracts.
Although written in Kotlin, Starknet-jvm has been created with compatibility with Java in mind.
Making synchronous requests
In Java
import com.swmansion.starknet.account.Account;
import com.swmansion.starknet.account.StandardAccount;
import com.swmansion.starknet.data.types.BlockTag;
import com.swmansion.starknet.data.types.Felt;
import com.swmansion.starknet.provider.Provider;
import com.swmansion.starknet.provider.Request;
import com.swmansion.starknet.provider.rpc.JsonRpcProvider;
public class Main {
public static void main(String[] args) {
// Create a provider for interacting with Starknet
Provider provider = new JsonRpcProvider("https://example-node-url.com/rpc");
// Create an account interface
Felt accountAddress = Felt.fromHex("0x13241455");
Felt privateKey = Felt.fromHex("0x425125");
Account account = new StandardAccount(provider, accountAddress, privateKey);
// Make a request
Felt contractAddress = Felt.fromHex("0x42362362436");
Felt storageKey = Felt.fromHex("0x13241253414");
Request<Felt> request = account.getStorageAt(contractAddress, storageKey, BlockTag.LATEST);
Felt response = request.send();
System.out.println(response);
}
}
Content copied to clipboard
In Kotlin
import com.swmansion.starknet.account.StandardAccount
import com.swmansion.starknet.data.types.BlockTag
import com.swmansion.starknet.data.types.Felt
import com.swmansion.starknet.provider.rpc.JsonRpcProvider
fun main() {
// Create a provider for interacting with Starknet
val provider = JsonRpcProvider("https://example-node-url.com/rpc")
// Create an account interface
val accountAddress = Felt.fromHex("0x1052524524")
val privateKey = Felt.fromHex("0x4232362662")
val account = StandardAccount(provider, accountAddress, privateKey)
// Make a request
val contractAddress = Felt.fromHex("0x423623626")
val storageKey = Felt.fromHex("0x132412414")
val request = account.getStorageAt(contractAddress, storageKey, BlockTag.LATEST)
val response = request.send()
println(response)
}
Content copied to clipboard
Making asynchronous requests
It is also possible to make asynchronous requests. Request.sendAsync()
returns a CompletableFuture
that can be than handled in preferred way.
In Java
import com.swmansion.starknet.account.Account;
import com.swmansion.starknet.account.StandardAccount;
import com.swmansion.starknet.data.types.BlockTag;
import com.swmansion.starknet.data.types.Felt;
import com.swmansion.starknet.provider.Provider;
import com.swmansion.starknet.provider.Request;
import com.swmansion.starknet.provider.rpc.JsonRpcProvider;
import java.util.concurrent.CompletableFuture;
public class Main {
public static void main(String[] args) {
// Create a provider for interacting with Starknet
Provider provider = new JsonRpcProvider("https://example-node-url.com/rpc");
// Create an account interface
Felt accountAddress = Felt.fromHex("0x13241455");
Felt privateKey = Felt.fromHex("0x425125");
Account account = new StandardAccount(provider, accountAddress, privateKey);
// Make a request
Felt contractAddress = Felt.fromHex("0x42362362436");
Felt storageKey = Felt.fromHex("0x13241253414");
Request<Felt> request = account.getStorageAt(contractAddress, storageKey, BlockTag.LATEST);
CompletableFuture<Felt> response = request.sendAsync();
response.thenAccept(System.out::println);
}
}
Content copied to clipboard
In Kotlin
import com.swmansion.starknet.account.StandardAccount
import com.swmansion.starknet.data.types.BlockTag
import com.swmansion.starknet.data.types.Felt
import com.swmansion.starknet.provider.rpc.JsonRpcProvider
fun main() {
// Create a provider for interacting with Starknet
val provider = JsonRpcProvider("https://example-node-url.com/rpc")
// Create an account interface
val accountAddress = Felt.fromHex("0x1052524524")
val privateKey = Felt.fromHex("0x4232362662")
val account = StandardAccount(provider, accountAddress, privateKey)
// Make an asynchronous request
val contractAddress = Felt.fromHex("0x423623626")
val storageKey = Felt.fromHex("0x132412414")
val request = account.getStorageAt(contractAddress, storageKey, BlockTag.LATEST)
val future = request.sendAsync()
future.thenAccept { println(it) }
}
Content copied to clipboard
Deploying account
In Java
import com.swmansion.starknet.account.Account;
import com.swmansion.starknet.account.StandardAccount;
import com.swmansion.starknet.crypto.StarknetCurve;
import com.swmansion.starknet.data.ContractAddressCalculator;
import com.swmansion.starknet.data.types.*;
import com.swmansion.starknet.data.types.transactions.*;
import com.swmansion.starknet.data.types.transactions.TransactionReceipt;
import com.swmansion.starknet.provider.Provider;
import com.swmansion.starknet.provider.rpc.JsonRpcProvider;
import java.math.BigInteger;
import java.util.List;
public class Main {
public static void main(String[] args) {
// Create a provider for interacting with Starknet
Provider provider = new JsonRpcProvider("https://example-node-url.com/rpc");
// Create an account interface
Felt privateKey = Felt.fromHex("0x123");
Felt publicKey = StarknetCurve.getPublicKey(privateKey);
// Use the class hash of the desired account contract (i.e. the class hash of OpenZeppelin account contract)
Felt classHash = Felt.fromHex("0x058d97f7d76e78f44905cc30cb65b91ea49a4b908a76703c54197bca90f81773");
Felt salt = new Felt(789);
List<Felt> calldata = List.of(publicKey);
Felt address = ContractAddressCalculator.calculateAddressFromHash(
classHash,
calldata,
salt
);
Account account = new StandardAccount(address, privateKey, provider, Felt.ZERO);
Felt maxFee = Felt.fromHex("0x11fcc58c7f7000"); // should be 10*fee from estimate deploy account fee
// Make sure to prefund the address with at least maxFee
// Create and sign deploy account transaction
DeployAccountTransactionPayload payload = account.signDeployAccount(
classHash,
calldata,
salt,
maxFee
);
DeployAccountResponse response = provider.deployAccount(payload).send();
}
}
Content copied to clipboard
In Kotlin
fun main(args: Array<String>) {
// Create a provider for interacting with Starknet
val provider = JsonRpcProvider("https://example-node-url.com/rpc")
// Create an account interface
val privateKey = Felt.fromHex("0x123")
val publicKey = StarknetCurve.getPublicKey(privateKey)
// Use the class hash of desired account contract (i.e. the class hash of OpenZeppelin account contract)
val classHash = Felt.fromHex("0x058d97f7d76e78f44905cc30cb65b91ea49a4b908a76703c54197bca90f81773")
val salt = Felt(789)
val calldata = listOf(publicKey)
val address = ContractAddressCalculator.calculateAddressFromHash(
classHash = classHash,
calldata = calldata,
salt = salt,
)
val account = StandardAccount(
address,
privateKey,
provider,
)
val payload = account.signDeployAccount(
classHash = classHash,
salt = salt,
calldata = calldata,
maxFee = Felt.fromHex("0x11fcc58c7f7000"), // should be 10*fee from estimate deploy account fee
)
// Create and sign deploy account transaction
val response = provider.deployAccount(payload).send()
}
Content copied to clipboard
Invoking contract: Transfering ETH
In Java
import com.swmansion.starknet.account.Account;
import com.swmansion.starknet.account.StandardAccount;
import com.swmansion.starknet.data.types.*;
import com.swmansion.starknet.provider.Provider;
import com.swmansion.starknet.provider.rpc.JsonRpcProvider;
import com.swmansion.starknet.provider.Request;
import java.math.BigInteger;
import java.util.List;
public class Main {
public static void main(String[] args) {
// Create a provider for interacting with Starknet
Provider provider = new JsonRpcProvider("https://example-node-url.com/rpc");
// Set up an account
Felt privateKey = Felt.fromHex("0x123");
Felt accountAddress = Felt.fromHex("0x1236789");
// ⚠️ WARNING ⚠️ Both the account address and private key have examples values for demonstration purposes only.
Account account = new StandardAccount(accountAddress, privateKey, provider, Felt.ZERO);
Felt recipientAccountAddress = Felt.fromHex("0x987654321");
Uint256 amount = new Uint256(new Felt(451));
// Specify the contract address, in this example ETH ERC20 contract is used
Felt contractAddress = Felt.fromHex("0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7");
// Create a call
List<Felt> calldata = List.of(recipientAccountAddress, amount.getLow(), amount.getHigh()); // amount is Uint256 and is represented by two Felt values
Call call = new Call(contractAddress, "transfer", calldata);
// Estimate fee for the invoke transaction
Felt estimateFee = account.estimateFee(List.of(call)).send().get(0).getOverallFee();
// Make sure to prefund the account with enough funds to cover the transaction fee and the amount to be transferred
// Create and sign invoke transaction
Request<InvokeFunctionResponse> request = account.execute(call);
// Send the transaction
InvokeFunctionResponse response = request.send();
}
}
Content copied to clipboard
In Kotlin
fun main(args: Array<String>) {
// Create a provider for interacting with Starknet
val provider = JsonRpcProvider("https://example-node-url.com/rpc")
// Set up an account
val privateKey = Felt.fromHex("0x123")
val accountAddress = Felt.fromHex("0x1236789")
// ⚠️ WARNING ⚠️ Both the account address and private key have examples values for demonstration purposes only.
val account = StandardAccount(accountAddress, privateKey, provider)
val recipientAccountAddress = Felt.fromHex("0x987654321")
// Make sure to prefund the account with enough funds to cover the transaction fee and the amount to be transferred
// account.execute(Call) estimates the fee automatically
// If you want to estimate the fee manually, please refer to the "Estimate Fee" example
val amount = Uint256(Felt(451))
// Specify the contract address, in this example ETH ERC20 contract is used
val contractAddress = Felt.fromHex("0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7")
// Create a call
val calldata = listOf(recipientAccountAddress, amount.low, amount.high) // amount is Uint256 and is represented by two Felt values
val call = Call(
contractAddress = contractAddress,
entrypoint = "transfer",
calldata = calldata,
)
// Estimate fee for the invoke transaction
val estimateFee = account.estimateFee(listOf(call)).send().first().overallFee
// Make sure to prefund the account with enough funds to cover the transaction fee and the amount to be transferred
// Create and sign invoke transaction
val request = account.execute(call)
// Send the transaction
val response = request.send()
}
Content copied to clipboard
Calling contract: Fetching ETH balance
In Java
import com.swmansion.starknet.account.Account;
import com.swmansion.starknet.account.StandardAccount;
import com.swmansion.starknet.provider.Provider;
import com.swmansion.starknet.data.types.*;
import com.swmansion.starknet.provider.Request;
import com.swmansion.starknet.provider.rpc.JsonRpcProvider;
import java.math.BigInteger;
import java.util.List;
public class Main {
public static void main(String[] args) {
// Create a provider for interacting with Starknet
Provider provider = new JsonRpcProvider("https://example-node-url.com/rpc");
// Set up an account
Felt privateKey = Felt.fromHex("0x123");
Felt accountAddress = Felt.fromHex("0x1236789");
// ⚠️ WARNING ⚠️ Both the account address and key are for demonstration purposes only.
Account account = new StandardAccount(accountAddress, privateKey, provider, Felt.ZERO);
// Specify the contract address, in this example ETH ERC20 contract is used
Felt contractAddress = Felt.fromHex("0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7");
// Create a call
List<Felt> calldata = List.of(account.getAddress());
Call call = new Call(contractAddress, "balanceOf", calldata);
Request<List<Felt>> request = provider.callContract(call);
// Send the call request
List<Felt> response = request.send();
//Output value's type is Uint256 and is represented by two Felt values
Uint256 balance = new Uint256(response.get(0), response.get(1));
}
}
Content copied to clipboard
In Kotlin
fun main(args: Array<String>) {
// Create a provider for interacting with Starknet
val provider = JsonRpcProvider("https://example-node-url.com/rpc")
// Set up an account
val privateKey = Felt.fromHex("0x123")
val accountAddress = Felt.fromHex("0x1236789")
// ⚠️ WARNING ⚠️ Both the account address and private key have examples values for demonstration purposes only.
val account = StandardAccount(accountAddress, privateKey, provider)
// Specify the contract address, in this example ETH ERC20 contract is used
val contractAddress = Felt.fromHex("0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7")
// Create a call
val calldata = listOf(account.address)
val call = Call(
contractAddress = contractAddress,
entrypoint = "balanceOf",
calldata = calldata,
)
val request = provider.callContract(call)
// Send the call request
val response: List<Felt> = request.send()
//Output value's type is Uint256 and is represented by two Felt values
val balance = Uint256(
low = response[0],
high = response[1],
)
}
Content copied to clipboard
Declaring Cairo 0 contract
In Java
import com.swmansion.starknet.account.Account;
import com.swmansion.starknet.account.StandardAccount;
import com.swmansion.starknet.data.types.transactions.DeclareTransactionV1Payload;
import com.swmansion.starknet.provider.Provider;
import com.swmansion.starknet.data.types.*;
import com.swmansion.starknet.provider.Request;
import com.swmansion.starknet.provider.rpc.JsonRpcProvider;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
public class Main {
public static void main(String[] args) {
// Create a provider for interacting with Starknet
Provider provider = new JsonRpcProvider("https://example-node-url.com/rpc");
// Set up an account
Felt privateKey = Felt.fromHex("0x1234");
Felt accountAddress = Felt.fromHex("0x1236789");
// ⚠️ WARNING ⚠️ Both the account address and private key are for demonstration purposes only.
Account account = new StandardAccount(accountAddress, privateKey, provider, Felt.ZERO);
// Import a compiled contract
Path contractPath = Paths.get("contract.json");
String contractCode = String.join("", Files.readAllLines(contractPath));
Cairo0ContractDefinition contractDefinition = new Cairo0ContractDefinition(contractCode);
// Class hash is calculated using the tools you used for compilation (only for Cairo v0 contracts)
Felt classHash = Felt.fromHex("0x1a3b2c");
Felt nonce = account.getNonce().send();
// Estimate fee for declaring a contract
DeclareTransactionV1Payload declareTransactionPayloadForFeeEstimate = account.signDeclare(contractDefinition, classHash, new ExecutionParams(nonce, new Felt(1000000000000000L)), false);
Request<List<EstimateFeeResponse>> feeEstimateRequest = provider.getEstimateFee(List.of(declareTransactionPayloadForFeeEstimate));
Felt feeEstimate = feeEstimateRequest.send().get(0).getOverallFee();
// Make sure to prefund the account with enough funds to cover the fee for declare transaction
// Declare a contract
Felt maxFee = new Felt(feeEstimate.getValue().multiply(BigInteger.TWO)); // Sometimes the actual fee may be higher than value from estimateFee
ExecutionParams params = new ExecutionParams(nonce, maxFee);
DeclareTransactionV1Payload declareTransactionPayload = account.signDeclare(contractDefinition, classHash, params, false);
Request<DeclareResponse> request = provider.declareContract(declareTransactionPayload);
DeclareResponse response = request.send();
Felt hash = response.getTransactionHash(); // Hash of the transaction that declares a contract
}
}
Content copied to clipboard
In Kotlin
fun main(args: Array<String>) {
// Create a provider for interacting with Starknet
val provider = JsonRpcProvider("https://example-node-url.com/rpc")
// Set up an account
val privateKey = Felt.fromHex("0x123")
val accountAddress = Felt.fromHex("0x1236789")
// ⚠️ WARNING ⚠️ Both the account address and private key are for demonstration purposes only.
val account = StandardAccount(accountAddress, privateKey, provider)
// Import a compiled contract
val contractCode = Path.of("contract.json").readText()
val contractDefinition = Cairo0ContractDefinition(contractCode)
// Class hash is calculated using the tools you used for compilation (only for Cairo v0 contracts)
val classHash = Felt.fromHex("0x1a3b2c")
val nonce = account.getNonce().send()
// Estimate fee for declaring a contract
val declareTransactionPayloadForFeeEstimate = account.signDeclare(
contractDefinition = contractDefinition,
classHash = classHash,
params = ExecutionParams(nonce, Felt(1000000000000000L)),
forFeeEstimate = true,
)
val feeEstimateRequest = provider.getEstimateFee(listOf(declareTransactionPayloadForFeeEstimate))
val feeEstimate = feeEstimateRequest.send().first().overallFee
// Make sure to prefund the account with enough funds to cover the fee for declare transaction
// Declare a contract
val maxFee = Felt(feeEstimate.value.multiply(BigInteger.TWO)) // Sometimes the actual fee may be higher than value from estimateFee
val params = ExecutionParams(
nonce = nonce,
maxFee = maxFee,
)
val declareTransactionPayload = account.signDeclare(
contractDefinition = contractDefinition,
classHash = classHash,
params = params,
)
val request = provider.declareContract(declareTransactionPayload)
val response = request.send()
}
Content copied to clipboard
Declaring Cairo 1/2 contract
In Java
import com.swmansion.starknet.account.Account;
import com.swmansion.starknet.account.StandardAccount;
import com.swmansion.starknet.data.types.transactions.DeclareTransactionV2Payload;
import com.swmansion.starknet.data.types.*;
import com.swmansion.starknet.provider.Provider;
import com.swmansion.starknet.provider.Request;
import com.swmansion.starknet.provider.rpc.JsonRpcProvider;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
public class Main {
public static void main(String[] args) {
// Create a provider for interacting with Starknet
Provider provider = new JsonRpcProvider("https://example-node-url.com/rpc");
// Set up an account
Felt privateKey = Felt.fromHex("0x1234");
Felt accountAddress = Felt.fromHex("0x1236789");
// ⚠️ WARNING ⚠️ Both the account address and private key are for demonstration purposes only.
Account account = new StandardAccount(accountAddress, privateKey, provider, Felt.ZERO);
// Import a compiled contract
Path contractPath = Paths.get("contract.json");
Path casmPath = Paths.get("contract.casm");
String contractCode = String.join("", Files.readAllLines(contractPath));
String casmCode = String.join("", Files.readAllLines(casmPath));
Cairo1ContractDefinition contractDefinition = new Cairo1ContractDefinition(contractCode);
CasmContractDefinition casmContractDefinition = new CasmContractDefinition(casmCode);
Felt nonce = account.getNonce().send();
// Estimate fee for declaring a contract
DeclareTransactionV2Payload declareTransactionPayloadForFeeEstimate = account.signDeclare(contractDefinition, casmContractDefinition, new ExecutionParams(nonce, new Felt(1000000000000000L)), false);
Request<List<EstimateFeeResponse>> feeEstimateRequest = provider.getEstimateFee(List.of(declareTransactionPayloadForFeeEstimate));
Felt feeEstimate = feeEstimateRequest.send().get(0).getOverallFee();
// Make sure to prefund the account with enough funds to cover the fee for declare transaction
// Declare a contract
Felt maxFee = new Felt(feeEstimate.getValue().multiply(BigInteger.TWO)); // Sometimes the actual fee may be higher than value from estimateFee
ExecutionParams params = new ExecutionParams(nonce, maxFee);
DeclareTransactionV2Payload declareTransactionPayload = account.signDeclare(contractDefinition, casmContractDefinition, params, false);
Request<DeclareResponse> request = provider.declareContract(declareTransactionPayload);
DeclareResponse response = request.send();
Felt hash = response.getTransactionHash(); // Hash of the transaction that declares a contract
}
}
Content copied to clipboard
In Kotlin
fun main(args: Array<String>) {
// Create a provider for interacting with Starknet
val provider = JsonRpcProvider("https://example-node-url.com/rpc")
// Set up an account
val privateKey = Felt.fromHex("0x1234")
val accountAddress = Felt.fromHex("0x1236789")
// ⚠️ WARNING ⚠️ Both the account address and private key are for demonstration purposes only.
val account = StandardAccount(accountAddress, privateKey, provider)
// Import a compiled contract
val contractCode = Path.of("contract.json").readText()
val casmCode = Path.of("contract.casm").readText()
val contractDefinition = Cairo1ContractDefinition(contractCode)
val casmContractDefinition = CasmContractDefinition(casmCode)
val nonce = account.getNonce().send()
// Estimate fee for declaring a contract
val declareTransactionPayloadForFeeEstimate = account.signDeclare(
sierraContractDefinition = contractDefinition,
casmContractDefinition = casmContractDefinition,
params = ExecutionParams(nonce, Felt(1000000000000000L)),
)
val feeEstimateRequest = provider.getEstimateFee(listOf(declareTransactionPayloadForFeeEstimate))
val feeEstimate = feeEstimateRequest.send().first().overallFee
// Make sure to prefund the account with enough funds to cover the fee for declare transaction
// Declare a contract
val maxFee = Felt(feeEstimate.value.multiply(BigInteger.TWO)) // Sometimes the actual fee may be higher than value from estimateFee
val params = ExecutionParams(
nonce = nonce,
maxFee = maxFee,
)
val declareTransactionPayload = account.signDeclare(
sierraContractDefinition = contractDefinition,
casmContractDefinition = casmContractDefinition,
params = params,
)
val request = provider.declareContract(declareTransactionPayload)
val response = request.send()
}
Content copied to clipboard
Packages
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Provider implementing the JSON RPC interface to communicate with the network.
Link copied to clipboard
Link copied to clipboard