Skip to content

Commit

Permalink
Merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
DelevoXDG committed Jan 23, 2024
2 parents 83e32be + 633580c commit f251ac2
Show file tree
Hide file tree
Showing 28 changed files with 479 additions and 296 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

runs-on: ${{ matrix.os }}
env:
DEVNET_SHA: 85495efb71a37ad3921c8986474b7e78a9a9f5fc
DEVNET_SHA: 1bd447d8ac8c2fb0a3eaf2d54512671f4a16c7ba
steps:
- uses: actions/checkout@v3
with:
Expand Down Expand Up @@ -91,14 +91,14 @@ jobs:
DEVNET_PATH: ${{ github.workspace }}/starknet-devnet-rs/target/release/starknet-devnet
NETWORK_TEST_MODE: "disabled"
NETWORK_TEST_NETWORK_NAME: "TESTNET"
TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }}
TESTNET_ACCOUNT_ADDRESS: ${{ secrets.TESTNET_ACCOUNT_ADDRESS }}
TESTNET_PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }}
TESTNET_CONST_NONCE_ACCOUNT_ADDRESS: ${{ secrets.TESTNET_CONST_NONCE_ACCOUNT_ADDRESS }}
TESTNET_CONST_NONCE_PRIVATE_KEY: ${{ secrets.TESTNET_CONST_NONCE_PRIVATE_KEY }}
GOERLI_TESTNET_RPC_URL: ${{ secrets.TESTNET_RPC_URL }}
GOERLI_TESTNET_ACCOUNT_ADDRESS: ${{ secrets.TESTNET_ACCOUNT_ADDRESS }}
GOERLI_TESTNET_PRIVATE_KEY: ${{ secrets.TESTNET_PRIVATE_KEY }}
GOERLI_TESTNET_CONST_NONCE_ACCOUNT_ADDRESS: ${{ secrets.TESTNET_CONST_NONCE_ACCOUNT_ADDRESS }}
GOERLI_TESTNET_CONST_NONCE_PRIVATE_KEY: ${{ secrets.TESTNET_CONST_NONCE_PRIVATE_KEY }}
run: ./gradlew :lib:koverXmlReport --info

- name: Upload coverage to Codecov
uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70
with:
files: lib/build/reports/kover/project-xml/report.xml
files: lib/build/reports/kover/report.xml
38 changes: 24 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ 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", StarknetChainId.TESTNET);
Provider provider = new JsonRpcProvider("https://example-node-url.com/rpc");

// Create an account interface
Felt accountAddress = Felt.fromHex("0x13241455");
Expand Down Expand Up @@ -93,7 +93,7 @@ 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", StarknetChainId.TESTNET);
Provider provider = new JsonRpcProvider("https://example-node-url.com/rpc");

// Create an account interface
Felt accountAddress = Felt.fromHex("0x13241455");
Expand Down Expand Up @@ -133,16 +133,16 @@ This way you reuse connections and thread pools.

**Do:**
```java
var provider = new JsonRpcProvider("https://example-node-url.com/rpc", StarknetChainId.TESTNET);
var provider = new JsonRpcProvider("https://example-node-url.com/rpc");
var account1 = new StandardAccount(provider, accountAddress1, privateKey1);
var account2 = new StandardAccount(provider, accountAddress2, privateKey2);
```

**Don't:**
```java
var provider1 = new JsonRpcProvider("https://example-node-url.com/rpc", StarknetChainId.TESTNET);
var provider1 = new JsonRpcProvider("https://example-node-url.com/rpc");
var account1 = new StandardAccount(provider1, accountAddress1, privateKey1);
var provider2 = new JsonRpcProvider("https://example-node-url.com/rpc", StarknetChainId.TESTNET);
var provider2 = new JsonRpcProvider("https://example-node-url.com/rpc");
var account2 = new StandardAccount(provider2, accountAddress2, privateKey2);
```

Expand Down Expand Up @@ -180,10 +180,25 @@ Use the following command to run tests:
```

### Network Tests
Running tests on networks (integration or testnet) requires a valid configuration. It can be set using environment variables in your system or IDE, or by sourcing an `.env` file.
Running tests on networks requires a valid configuration. It can be set using environment variables in your system or IDE, or by sourcing an `.env` file.
Refer to the example config found in [test_variables.env.example](test_variables.env.example).
To select the network, please set the `NETWORK_TEST_NETWORK_NAME` environment variable. Currenty, the allowed options are `INTEGRATION` and `TESTNET`.
You will also need to provide an **RPC node URL** and an **account address** (along with its **private key**).
To select the network, please set the `NETWORK_TEST_NETWORK_NAME` environment variable. Currenty, the allowed options are:
- `SEPOLIA_TESTNET`
- `SEPOLIA_INTEGRATION`
- `GOERLI_TESTNET`
- `GOERLI_INTEGRATION`

Please note that `GOERLI` networks are deprecated, and won't be supported in the future. The number of tests working on `SEPOLIA` is, however, temporarily limited.
To properly configure your network, ensure the following variables are set with the `NETWORK_NAME_` prefix:
- `RPC_URL` - url of your RPC node
- `ACCOUNT_ADDRESS` and `PRIVATE_KEY` - address and private key of your account
Additionally, you can also set:
- `CONST_NONCE_ACCOUNT_ADDRESS` and `CONST_NONCE_PRIVATE_KEY` - address and private key exclusively for non-gas network tests, preventing potential inconsistencies (sometimes, `getNonce` may report higher nonce than expected).
Recommended for reliable non-gas testing.
These default to `ACCOUNT_ADDRESS` and `PRIVATE_KEY` if not set.
- `ACCOUNT_CAIRO_VERSION` - Cairo version of the `ACCOUNT_ADDRESS` and `CONST_NONCE_ACCOUNT_ADDRESS` accounts. Defaults to `0`.
Network tests are disabled by default. To enable them, you can set the environment variable:
```env
NETWORK_TEST_MODE=non_gas
Expand All @@ -199,12 +214,7 @@ Alternatively, you can use flag to specify whether to run network and gas tests:
./gradlew :lib:test -PnetworkTestMode=non_gas
./gradlew :lib:test -PnetworkTestMode=all
```
Flag takes precendece over the env variable if both are set.

⚠️ WARNING ⚠️ Some network tests may fail due to `getNonce` receiving higher nonce than expected by other methods.
It is adviced to additionaly provide an account (along with its **private key**) with a constant **nonce** to ensure non-gas tests pass.
Such account shouldn't be used for any other purpose than running non-gas network tests.
If not set, the main account provided in the config will be used for this purpose.
Flag takes precendece over the environment variable if both are set.
### Ensuring idiomatic Java code
We want this library to be used by both kotlin & java users. In order to ensure a nice API for java always follow those rules:
Expand Down
2 changes: 1 addition & 1 deletion androiddemo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Running the demo on a network other than devnet (Mainnet/Testen/Integration) req
### Prerequisites
- Android emulator (Android Studio, IntelliJ IDEA, etc.)
- URL of a Starknet RPC node.
- Account deployed on said network with some funds on it. If you're using **testnet**, you can obtain some funds from the [faucet](https://faucet.goerli.starknet.io/).
- Account deployed on said network with some funds on it. If you're using **Goerli testnet**, you can obtain some funds from the [faucet](https://faucet.goerli.starknet.io/).
- A valid configuration that consists of the data above:
- `DEMO_RPC_URL` - RPC node URL
- `DEMO_ACCOUNT_ADDRESS` - account address
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class MainActivity : AppCompatActivity() {
// Display the receipt details in the UI
withContext(Dispatchers.Main) {
receiptExecutionStatusValue.text = receipt.executionStatus.toString()
receiptActualFeeValue.text = receipt.actualFee?.let { "${it.value} wei" } ?: getString(R.string.not_available)
receiptActualFeeValue.text = receipt.actualFee.let { "${it.amount.value} ${it.unit.toString().lowercase()}" }
receiptRevertReasonValue.text = receipt.revertReason ?: getString(R.string.not_available)
}
} catch (e: RpcRequestFailedException) {
Expand Down
2 changes: 1 addition & 1 deletion javademo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Running the demo on a network other than devnet (Mainnet/Testen/Integration) req
### Prerequisites
- URL of a Starknet RPC node.
- Details (address and private key) of an account deployed on said network with some funds on it.
If you're using **testnet**, you can obtain some funds from the [faucet](https://faucet.goerli.starknet.io/).
If you're using **Goerli testnet**, you can obtain some funds from the [faucet](https://faucet.goerli.starknet.io/).
- [`asdf`](https://github.com/asdf-vm/asdf) version manager with [`asdf scarb`](https://github.com/software-mansion/asdf-scarb) plugin
### Steps
Expand Down
5 changes: 3 additions & 2 deletions javademo/src/main/java/com/example/javademo/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.swmansion.starknet.data.types.transactions.DeclareTransactionV2Payload;
import com.swmansion.starknet.data.types.transactions.TransactionReceipt;
import com.swmansion.starknet.deployercontract.ContractDeployment;
import com.swmansion.starknet.deployercontract.Deployer;
import com.swmansion.starknet.deployercontract.StandardDeployer;
import com.swmansion.starknet.provider.Provider;
import com.swmansion.starknet.provider.Request;
Expand Down Expand Up @@ -37,7 +38,7 @@ private static class DemoConfig {

public static void main(String[] args) throws Exception {
// Create a provider for interacting with Starknet
JsonRpcProvider provider = new JsonRpcProvider(DemoConfig.rpcNodeUrl, StarknetChainId.TESTNET);
Provider provider = new JsonRpcProvider(DemoConfig.rpcNodeUrl, StarknetChainId.TESTNET);

// Set up an account
// Please note the account must be deployed and have enough funds to paying the fees
Expand Down Expand Up @@ -167,7 +168,7 @@ private static DeployContractResult deployContract(Account account, Provider pro
Felt salt = new Felt(20);

// Deploy a contract
StandardDeployer contractDeployer = new StandardDeployer(udcAddress, provider, account);
Deployer contractDeployer = new StandardDeployer(udcAddress, provider, account);
Request<ContractDeployment> deployRequest = contractDeployer.deployContract(classHash, true, salt, constructorCalldata);
ContractDeployment deployResponse = deployRequest.send();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class StandardAccount(
private val provider: Provider,
private val cairoVersion: Felt = Felt.ZERO,
) : Account {
private val chainId: StarknetChainId by lazy { provider.getChainId().send() }
private fun estimateVersion(version: Felt): Felt {
return BigInteger.valueOf(2).pow(128)
.add(version.value)
Expand Down Expand Up @@ -57,7 +58,7 @@ class StandardAccount(
val tx = TransactionFactory.makeInvokeV1Transaction(
senderAddress = address,
calldata = calldata,
chainId = provider.chainId,
chainId = chainId,
nonce = params.nonce,
maxFee = params.maxFee,
version = signVersion,
Expand All @@ -77,7 +78,7 @@ class StandardAccount(
val tx = TransactionFactory.makeInvokeV3Transaction(
senderAddress = address,
calldata = calldata,
chainId = provider.chainId,
chainId = chainId,
nonce = params.nonce,
version = signVersion,
resourceBounds = params.resourceBounds,
Expand Down Expand Up @@ -110,7 +111,7 @@ class StandardAccount(
contractAddress = address,
salt = salt,
calldata = calldata,
chainId = provider.chainId,
chainId = chainId,
maxFee = maxFee,
version = signVersion,
nonce = nonce,
Expand All @@ -136,7 +137,7 @@ class StandardAccount(
senderAddress = address,
salt = salt,
calldata = calldata,
chainId = provider.chainId,
chainId = chainId,
version = signVersion,
nonce = params.nonce,
resourceBounds = params.resourceBounds,
Expand Down Expand Up @@ -164,7 +165,7 @@ class StandardAccount(
contractDefinition = contractDefinition,
classHash = classHash,
senderAddress = address,
chainId = provider.chainId,
chainId = chainId,
nonce = params.nonce,
maxFee = params.maxFee,
version = signVersion,
Expand All @@ -187,7 +188,7 @@ class StandardAccount(
val tx = TransactionFactory.makeDeclareV2Transaction(
contractDefinition = sierraContractDefinition,
senderAddress = address,
chainId = provider.chainId,
chainId = chainId,
nonce = params.nonce,
maxFee = params.maxFee,
version = signVersion,
Expand All @@ -211,7 +212,7 @@ class StandardAccount(
val tx = TransactionFactory.makeDeclareV3Transaction(
contractDefinition = sierraContractDefinition,
senderAddress = address,
chainId = provider.chainId,
chainId = chainId,
nonce = params.nonce,
version = signVersion,
resourceBounds = params.resourceBounds,
Expand Down Expand Up @@ -433,7 +434,7 @@ class StandardAccount(
val signedTransaction = TransactionFactory.makeInvokeV1Transaction(
senderAddress = payload.senderAddress,
calldata = payload.calldata,
chainId = provider.chainId,
chainId = chainId,
nonce = nonce,
maxFee = payload.maxFee,
signature = payload.signature,
Expand All @@ -452,7 +453,7 @@ class StandardAccount(
val signedTransaction = TransactionFactory.makeInvokeV3Transaction(
senderAddress = payload.senderAddress,
calldata = payload.calldata,
chainId = provider.chainId,
chainId = chainId,
nonce = nonce,
signature = payload.signature,
version = payload.version,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package com.swmansion.starknet.data.types

import com.swmansion.starknet.data.selectorFromName
import com.swmansion.starknet.data.types.conversions.ConvertibleToCalldata
import com.swmansion.starknet.extensions.toCalldata
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

Expand Down Expand Up @@ -64,7 +65,7 @@ data class Call(
*/
@JvmStatic
fun fromCallArguments(contractAddress: Felt, entrypoint: Felt, arguments: CallArguments): Call {
val calldata = arguments.flatMap { it.toCalldata() }
val calldata = arguments.toCalldata()
return Call(contractAddress, entrypoint, calldata)
}

Expand Down
11 changes: 11 additions & 0 deletions lib/src/main/kotlin/com/swmansion/starknet/data/types/FeltArray.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.swmansion.starknet.data.types

import com.swmansion.starknet.data.types.conversions.ConvertibleToCalldata

data class FeltArray(private val list: MutableList<Felt>) : ConvertibleToCalldata, MutableList<Felt> by list {
constructor(vararg elements: Felt) : this(elements.toMutableList())
constructor(collection: Collection<Felt>) : this(collection.toMutableList())
constructor() : this(emptyList())

override fun toCalldata(): List<Felt> = list.toList()
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
package com.swmansion.starknet.data.types

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
enum class StarknetChainId(val value: Felt) {
@SerialName("0x534e5f4d41494e")
MAINNET(Felt.fromHex("0x534e5f4d41494e")), // encodeShortString('SN_MAIN'),
TESTNET(Felt.fromHex("0x534e5f474f45524c49")), // encodeShortString('SN_GOERLI'),

@Deprecated("Consider using SEPOLIA instead")
@SerialName("0x534e5f474f45524c49")
GOERLI(Felt.fromHex("0x534e5f474f45524c49")), // encodeShortString('SN_GOERLI'),

@SerialName("0x534e5f5345504f4c4941")
SEPOLIA_TESTNET(Felt.fromHex("0x534e5f5345504f4c4941")), // encodeShortString('SN_SEPOLIA'),]

@SerialName("0x534e5f494e544547524154494f4e5f5345504f4c4941")
SEPOLIA_INTEGRATION(Felt.fromHex("0x534e5f494e544547524154494f4e5f5345504f4c4941")), // encodeShortString('SN_INTEGRATION_SEPOLIA'),
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.swmansion.starknet.extensions

import com.swmansion.starknet.data.types.Felt
import com.swmansion.starknet.data.types.conversions.ConvertibleToCalldata

fun List<ConvertibleToCalldata>.toCalldata(): List<Felt> {
return this.flatMap { it.toCalldata() }
}
11 changes: 9 additions & 2 deletions lib/src/main/kotlin/com/swmansion/starknet/provider/Provider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import com.swmansion.starknet.provider.exceptions.RequestFailedException
* Implementers of this interface provide methods for interacting with Starknet, for example through Starknet JSON-RPC.
*/
interface Provider {
val chainId: StarknetChainId

/**
* Get a transaction.
*
Expand Down Expand Up @@ -632,6 +630,15 @@ interface Provider {
*/
fun getSyncing(): Request<Syncing>

/**
* Get the chain id.
*
* Get the currently configured Starknet chain id.
*
* @throws RequestFailedException
*/
fun getChainId(): Request<StarknetChainId>

/**
* Get a block with transactions.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,13 @@ import kotlinx.serialization.json.*
* httpService or provide it with your own httpService.
*
* @param url url of the service providing a rpc interface
* @param chainId an id of the network
* @param httpService service used for making http requests
*/
class JsonRpcProvider(
val url: String,
override val chainId: StarknetChainId,
private val httpService: HttpService,
) : Provider {
constructor(url: String, chainId: StarknetChainId) : this(url, chainId, OkHttpService())
constructor(url: String) : this(url, OkHttpService())

private val jsonWithDefaults = Json { encodeDefaults = true }

Expand Down Expand Up @@ -482,6 +480,12 @@ class JsonRpcProvider(
)
}

override fun getChainId(): Request<StarknetChainId> {
val params = Json.encodeToJsonElement(JsonArray(emptyList()))

return buildRequest(JsonRpcMethod.GET_CHAIN_ID, params, StarknetChainId.serializer())
}

private fun getBlockWithTxs(payload: GetBlockWithTransactionsPayload): Request<GetBlockWithTransactionsResponse> {
val jsonPayload = Json.encodeToJsonElement(payload)

Expand Down Expand Up @@ -620,6 +624,7 @@ private enum class JsonRpcMethod(val methodName: String) {
GET_BLOCK_HASH_AND_NUMBER("starknet_blockHashAndNumber"),
GET_BLOCK_TRANSACTION_COUNT("starknet_getBlockTransactionCount"),
GET_SYNCING("starknet_syncing"),
GET_CHAIN_ID("starknet_chainId"),
ESTIMATE_FEE("starknet_estimateFee"),
ESTIMATE_MESSAGE_FEE("starknet_estimateMessageFee"),
GET_BLOCK_WITH_TXS("starknet_getBlockWithTxs"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.junit.jupiter.api.Test
internal class TransactionHashCalculatorTest {
private val calldata = listOf(Felt(999), Felt(888), Felt(777))
private val maxFee = Felt.fromHex("0xabcd987654210")
private val chainId = StarknetChainId.TESTNET
private val chainId = StarknetChainId.GOERLI
private val version = Felt.ONE

@Test
Expand Down
Loading

0 comments on commit f251ac2

Please sign in to comment.