Skip to content

Commit

Permalink
Merge branch 'main' into fix/troubleshooting-emulator-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
elizabethengelman authored Jul 30, 2024
2 parents cba0bdc + 391be3a commit 1820100
Show file tree
Hide file tree
Showing 12 changed files with 142 additions and 36 deletions.
42 changes: 42 additions & 0 deletions .github/workflows/bindings-ts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: bindings typescript

on:
push:
branches: [main, release/**]
pull_request:

jobs:
test:
name: test generated libraries
runs-on: ubuntu-22.04
services:
rpc:
image: stellar/quickstart:testing
ports:
- 8000:8000
env:
ENABLE_LOGS: true
NETWORK: local
ENABLE_SOROBAN_RPC: true
options: >-
--health-cmd "curl --no-progress-meter --fail-with-body -X POST \"http://localhost:8000/soroban/rpc\" -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"id\":8675309,\"method\":\"getNetwork\"}' && curl --no-progress-meter \"http://localhost:8000/friendbot\" | grep '\"invalid_field\": \"addr\"'"
--health-interval 10s
--health-timeout 5s
--health-retries 50
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- run: rustup update
- run: cargo build
- run: rustup target add wasm32-unknown-unknown
- run: make build-test-wasms
- run: npm ci && npm run test
working-directory: cmd/crates/soroban-spec-typescript/ts-tests
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 12 additions & 12 deletions cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cmd/crates/soroban-spec-typescript/ts-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"ava": "^5.3.1",
"dotenv": "^16.3.1",
"eslint": "^8.53.0",
"@stellar/stellar-sdk": "12.1.0",
"@stellar/stellar-sdk": "12.2.0",
"typescript": "^5.3.3"
},
"ava": {
Expand Down
15 changes: 11 additions & 4 deletions cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import { spawnSync } from "node:child_process";
import { Address, Keypair } from "@stellar/stellar-sdk";
import { basicNodeSigner } from "@stellar/stellar-sdk/ContractClient";
import { basicNodeSigner } from "@stellar/stellar-sdk/contract";

const rootKeypair = Keypair.fromSecret(spawnSync("./soroban", ["keys", "show", "root"], { shell: true, encoding: "utf8" }).stdout.trim());
const rootKeypair = Keypair.fromSecret(
spawnSync("./soroban", ["keys", "show", "root"], {
shell: true,
encoding: "utf8",
}).stdout.trim(),
);

export const root = {
keypair: rootKeypair,
address: Address.fromString(rootKeypair.publicKey()),
}
};

export const rpcUrl = process.env.SOROBAN_RPC_URL ?? "http://localhost:8000/";
export const networkPassphrase = process.env.SOROBAN_NETWORK_PASSPHRASE ?? "Standalone Network ; February 2017";
export const networkPassphrase =
process.env.SOROBAN_NETWORK_PASSPHRASE ??
"Standalone Network ; February 2017";

export const signer = basicNodeSigner(root.keypair, networkPassphrase);
1 change: 1 addition & 0 deletions cmd/crates/soroban-test/tests/it/integration.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod bindings;
mod custom_types;
mod dotenv;
mod fund;
mod hello_world;
mod tx;
mod util;
Expand Down
19 changes: 19 additions & 0 deletions cmd/crates/soroban-test/tests/it/integration/fund.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use soroban_test::TestEnv;

#[tokio::test]
#[allow(clippy::too_many_lines)]
async fn fund() {
let sandbox = &TestEnv::new();
sandbox
.new_assert_cmd("keys")
.arg("generate")
.arg("test")
.assert()
.success();
sandbox
.new_assert_cmd("keys")
.arg("fund")
.arg("test")
.assert()
.stderr(predicates::str::contains("funding failed"));
}
6 changes: 0 additions & 6 deletions cmd/crates/soroban-test/tests/it/integration/hello_world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,6 @@ async fn invoke() {
let sandbox = &TestEnv::new();
let c = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap();
let GetLatestLedgerResponse { sequence, .. } = c.get_latest_ledger().await.unwrap();
sandbox
.new_assert_cmd("keys")
.arg("fund")
.arg("test")
.assert()
.stderr(predicates::str::contains("Account already exists"));
sandbox
.new_assert_cmd("keys")
.arg("fund")
Expand Down
21 changes: 20 additions & 1 deletion cmd/soroban-cli/src/commands/contract/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ use std::str::FromStr;
use std::{fmt::Debug, fs, io};

use clap::{arg, command, Parser};
use stellar_xdr::curr::{ContractDataEntry, ContractExecutable, ScVal};

use crate::commands::contract::fetch::Error::{ContractIsStellarAsset, UnexpectedContractToken};
use crate::commands::{global, NetworkRunnable};
use crate::config::{
self, locator,
network::{self, Network},
};
use crate::utils::rpc::get_remote_wasm_from_hash;
use crate::{
rpc::{self, Client},
Pwd,
Expand Down Expand Up @@ -64,6 +67,13 @@ pub enum Error {
Network(#[from] network::Error),
#[error("cannot create contract directory for {0:?}")]
CannotCreateContractDir(PathBuf),
#[error("unexpected contract data {0:?}")]
UnexpectedContractToken(ContractDataEntry),
#[error(
"cannot fetch wasm for contract because the contract is \
a network built-in asset contract that does not have a downloadable code binary"
)]
ContractIsStellarAsset(),
}

impl From<Infallible> for Error {
Expand Down Expand Up @@ -126,6 +136,15 @@ impl NetworkRunnable for Cmd {
client
.verify_network_passphrase(Some(&network.network_passphrase))
.await?;
Ok(client.get_remote_wasm(&contract_id).await?)
let data_entry = client.get_contract_data(&contract_id).await?;
if let ScVal::ContractInstance(contract) = &data_entry.val {
return match &contract.executable {
ContractExecutable::Wasm(hash) => {
Ok(get_remote_wasm_from_hash(&client, hash).await?)
}
ContractExecutable::StellarAsset => Err(ContractIsStellarAsset()),
};
}
return Err(UnexpectedContractToken(data_entry));
}
}
14 changes: 7 additions & 7 deletions cmd/soroban-cli/src/config/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ pub enum Error {
FailedToParseJSON(String, serde_json::Error),
#[error("Invalid URL {0}")]
InvalidUrl(String),
#[error("Inproper response {0}")]
InproperResponse(String),
#[error("funding failed: {0}")]
FundingFailed(String),
}

#[derive(Debug, clap::Args, Clone, Default)]
Expand Down Expand Up @@ -149,16 +149,16 @@ impl Network {
return Err(Error::InvalidUrl(uri.to_string()));
}
};
let request_successful = response.status().is_success();
let body = hyper::body::to_bytes(response.into_body()).await?;
let res = serde_json::from_slice::<serde_json::Value>(&body)
.map_err(|e| Error::FailedToParseJSON(uri.to_string(), e))?;
tracing::debug!("{res:#?}");
if let Some(detail) = res.get("detail").and_then(Value::as_str) {
if detail.contains("createAccountAlreadyExist") {
eprintln!("Account already exists");
if !request_successful {
if let Some(detail) = res.get("detail").and_then(Value::as_str) {
return Err(Error::FundingFailed(detail.to_string()));
}
} else if res.get("successful").is_none() {
return Err(Error::InproperResponse(res.to_string()));
return Err(Error::FundingFailed("unknown cause".to_string()));
}
Ok(())
}
Expand Down
3 changes: 2 additions & 1 deletion cmd/soroban-cli/src/get_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub use soroban_spec_tools::contract as contract_spec;
use crate::commands::global;
use crate::config::{self, data, locator, network};
use crate::rpc;
use crate::utils::rpc::get_remote_wasm_from_hash;

#[derive(thiserror::Error, Debug)]
pub enum Error {
Expand Down Expand Up @@ -65,7 +66,7 @@ pub async fn get_remote_contract_spec(
if let Ok(entries) = data::read_spec(&hash_str) {
entries
} else {
let raw_wasm = client.get_remote_wasm_from_hash(hash).await?;
let raw_wasm = get_remote_wasm_from_hash(&client, &hash).await?;
let res = contract_spec::Spec::new(&raw_wasm)?;
let res = res.spec;
if global_args.map_or(true, |a| !a.no_cache) {
Expand Down
23 changes: 23 additions & 0 deletions cmd/soroban-cli/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,29 @@ pub fn contract_id_hash_from_asset(
Ok(Hash(Sha256::digest(preimage_xdr).into()))
}

pub mod rpc {
use soroban_env_host::xdr;
use soroban_rpc::{Client, Error};
use stellar_xdr::curr::{Hash, LedgerEntryData, LedgerKey, Limits, ReadXdr};

pub async fn get_remote_wasm_from_hash(client: &Client, hash: &Hash) -> Result<Vec<u8>, Error> {
let code_key = LedgerKey::ContractCode(xdr::LedgerKeyContractCode { hash: hash.clone() });
let contract_data = client.get_ledger_entries(&[code_key]).await?;
let entries = contract_data.entries.unwrap_or_default();
if entries.is_empty() {
return Err(Error::NotFound(
"Contract Code".to_string(),
hex::encode(hash),
));
}
let contract_data_entry = &entries[0];
match LedgerEntryData::from_xdr_base64(&contract_data_entry.xdr, Limits::none())? {
LedgerEntryData::ContractCode(xdr::ContractCodeEntry { code, .. }) => Ok(code.into()),
scval => Err(Error::UnexpectedContractCodeDataType(scval)),
}
}
}

pub mod parsing {

use regex::Regex;
Expand Down

0 comments on commit 1820100

Please sign in to comment.