Skip to content

Commit

Permalink
remote data fetching in remote and native, setting and cli params
Browse files Browse the repository at this point in the history
  • Loading branch information
hugocaillard committed Dec 2, 2024
1 parent babbc1d commit 0cf47fb
Show file tree
Hide file tree
Showing 20 changed files with 775 additions and 264 deletions.
22 changes: 21 additions & 1 deletion components/clarinet-cli/src/frontend/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use clarity_repl::clarity::vm::types::QualifiedContractIdentifier;
use clarity_repl::clarity::ClarityVersion;
use clarity_repl::frontend::terminal::print_clarity_wasm_warning;
use clarity_repl::repl::diagnostic::output_diagnostic;
use clarity_repl::repl::settings::{ApiUrl, RemoteDataSettings};
use clarity_repl::repl::{ClarityCodeSource, ClarityContract, ContractDeployer, DEFAULT_EPOCH};
use clarity_repl::{analysis, repl, Terminal};
use stacks_network::{self, DevnetOrchestrator};
Expand Down Expand Up @@ -334,6 +335,7 @@ struct Console {
/// Path to Clarinet.toml
#[clap(long = "manifest-path", short = 'm')]
pub manifest_path: Option<String>,

/// If specified, use this deployment file
#[clap(long = "deployment-plan-path", short = 'p')]
pub deployment_plan_path: Option<String>,
Expand All @@ -351,6 +353,17 @@ struct Console {
conflicts_with = "use_on_disk_deployment_plan"
)]
pub use_computed_deployment_plan: bool,

/// Enable remote data fetching from mainnet or a testnet
#[clap(long = "enable-remote-data", short = 'r')]
pub enable_remote_data: bool,
/// Set a custom Hiro API URL for remote data fetching
#[clap(long = "remote-data-api-url", short = 'a')]
pub remote_data_api_url: Option<ApiUrl>,
/// Initial remote Stacks block height
#[clap(long = "remote-data-initial-height", short = 'b')]
pub remote_data_initial_height: Option<u32>,

/// Allow the Clarity Wasm preview to run in parallel with the Clarity interpreter (beta)
#[clap(long = "enable-clarity-wasm")]
pub enable_clarity_wasm: bool,
Expand Down Expand Up @@ -941,6 +954,12 @@ pub fn main() {
}
},
Command::Console(cmd) => {
let remote_data_settings = RemoteDataSettings {
enabled: cmd.enable_remote_data,
api_url: cmd.remote_data_api_url.unwrap_or_default(),
initial_height: cmd.remote_data_initial_height,
};

// Loop to handle `::reload` command
loop {
let manifest = load_manifest_or_warn(cmd.manifest_path.clone());
Expand Down Expand Up @@ -988,7 +1007,8 @@ pub fn main() {
}
}
None => {
let settings = repl::SessionSettings::default();
let mut settings = repl::SessionSettings::default();
settings.repl_settings.remote_data = remote_data_settings.clone();
if cmd.enable_clarity_wasm {
let mut settings_wasm = repl::SessionSettings::default();
settings_wasm.repl_settings.clarity_wasm_mode = true;
Expand Down
12 changes: 6 additions & 6 deletions components/clarinet-deployments/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ pub fn update_session_with_deployment_plan(
update_session_with_genesis_accounts(session, deployment);

let mut boot_contracts = BTreeMap::new();
if !session.settings.repl_settings.network_simulation.enabled {
if !session.settings.repl_settings.remote_data.enabled {
let boot_contracts_data = BOOT_CONTRACTS_DATA.clone();

for (contract_id, (boot_contract, ast)) in boot_contracts_data {
Expand Down Expand Up @@ -348,11 +348,11 @@ pub async fn generate_default_deployment(
};
let session = Session::new(settings.clone());

let simnet_network_simulation = matches!(network, StacksNetwork::Simnet)
&& session.settings.repl_settings.network_simulation.enabled;
let simnet_remote_data = matches!(network, StacksNetwork::Simnet)
&& session.settings.repl_settings.remote_data.enabled;

let mut boot_contracts_ids = BTreeSet::new();
if !simnet_network_simulation {
if !simnet_remote_data {
let boot_contracts_data = BOOT_CONTRACTS_DATA.clone();
let mut boot_contracts_asts = BTreeMap::new();
for (id, (contract, ast)) in boot_contracts_data {
Expand Down Expand Up @@ -437,7 +437,7 @@ pub async fn generate_default_deployment(
clarity_version,
};

if !simnet_network_simulation {
if !simnet_remote_data {
emulated_contracts_publish.insert(contract_id.clone(), data);
}
} else if matches!(network, StacksNetwork::Devnet | StacksNetwork::Testnet) {
Expand Down Expand Up @@ -543,7 +543,7 @@ pub async fn generate_default_deployment(
}

// Avoid listing requirements as deployment transactions to the deployment specification on Mainnet
if !matches!(network, StacksNetwork::Mainnet) && !simnet_network_simulation {
if !matches!(network, StacksNetwork::Mainnet) && !simnet_remote_data {
let mut ordered_contracts_ids = match ASTDependencyDetector::order_contracts(
&requirements_deps,
&contract_epochs,
Expand Down
49 changes: 27 additions & 22 deletions components/clarinet-sdk-wasm/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ pub struct SDK {
contracts_interfaces: HashMap<QualifiedContractIdentifier, ContractInterface>,
session: Option<Session>,
file_accessor: Box<dyn FileAccessor>,
http_client: JsFunction,
options: SDKOptions,
current_test_name: String,
costs_reports: Vec<CostsReport>,
Expand All @@ -295,10 +296,14 @@ pub struct SDK {
#[wasm_bindgen]
impl SDK {
#[wasm_bindgen(constructor)]
pub fn new(fs_request: JsFunction, options: Option<SDKOptions>) -> Self {
pub fn new(
fs_request: JsFunction,
http_client: JsFunction,
options: Option<SDKOptions>,
) -> Self {
panic::set_hook(Box::new(console_error_panic_hook::hook));

let fs = Box::new(WASMFileSystemAccessor::new(fs_request));
let file_accessor = Box::new(WASMFileSystemAccessor::new(fs_request));

let track_coverage = options.as_ref().map_or(false, |o| o.track_coverage);
let track_costs = options.as_ref().map_or(false, |o| o.track_costs);
Expand All @@ -310,7 +315,8 @@ impl SDK {
contracts_interfaces: HashMap::new(),
contracts_locations: HashMap::new(),
session: None,
file_accessor: fs,
file_accessor,
http_client,
options: SDKOptions {
track_coverage,
track_costs,
Expand All @@ -337,12 +343,6 @@ impl SDK {
}
}

pub fn xhr_req(&self) -> Result<web_sys::XmlHttpRequest, JsValue> {
let xhr = web_sys::XmlHttpRequest::new();
log!("{:?}", xhr);
xhr
}

#[wasm_bindgen(js_name=getDefaultClarityVersionForCurrentEpoch)]
pub fn default_clarity_version_for_current_epoch(&self) -> ClarityVersionString {
let session = self.get_session();
Expand All @@ -355,7 +355,12 @@ impl SDK {

#[wasm_bindgen(js_name=initEmtpySession)]
pub async fn init_empty_session(&mut self) -> Result<(), String> {
let session = Session::new(SessionSettings::default());
let mut session = Session::new(SessionSettings::default());

session
.interpreter
.clarity_datastore
.set_http_client(self.http_client.clone());
self.session = Some(session);
Ok(())
}
Expand Down Expand Up @@ -783,10 +788,10 @@ impl SDK {

#[wasm_bindgen(js_name=callReadOnlyFn)]
pub fn call_read_only_fn(&mut self, args: &CallFnArgs) -> Result<TransactionRes, String> {
let interface = self.get_function_interface(&args.contract, &args.method)?;
if interface.access != ContractInterfaceFunctionAccess::read_only {
return Err(format!("{} is not a read-only function", &args.method));
}
// let interface = self.get_function_interface(&args.contract, &args.method)?;
// if interface.access != ContractInterfaceFunctionAccess::read_only {
// return Err(format!("{} is not a read-only function", &args.method));
// }
self.call_contract_fn(args, false)
}

Expand All @@ -795,10 +800,10 @@ impl SDK {
args: &CallFnArgs,
advance_chain_tip: bool,
) -> Result<TransactionRes, String> {
let interface = self.get_function_interface(&args.contract, &args.method)?;
if interface.access != ContractInterfaceFunctionAccess::public {
return Err(format!("{} is not a public function", &args.method));
}
// let interface = self.get_function_interface(&args.contract, &args.method)?;
// if interface.access != ContractInterfaceFunctionAccess::public {
// return Err(format!("{} is not a public function", &args.method));
// }

if advance_chain_tip {
let session = self.get_session_mut();
Expand All @@ -812,10 +817,10 @@ impl SDK {
args: &CallFnArgs,
advance_chain_tip: bool,
) -> Result<TransactionRes, String> {
let interface = self.get_function_interface(&args.contract, &args.method)?;
if interface.access != ContractInterfaceFunctionAccess::private {
return Err(format!("{} is not a private function", &args.method));
}
// let interface = self.get_function_interface(&args.contract, &args.method)?;
// if interface.access != ContractInterfaceFunctionAccess::private {
// return Err(format!("{} is not a private function", &args.method));
// }
if advance_chain_tip {
let session = self.get_session_mut();
session.advance_chain_tip(1);
Expand Down
16 changes: 8 additions & 8 deletions components/clarinet-sdk-wasm/src/test_wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use wasm_bindgen_test::*;

async fn init_sdk() -> SDK {
let js_noop = JsFunction::new_no_args("return");
let mut sdk = SDK::new(js_noop, None);
let mut sdk = SDK::new(js_noop.clone(), js_noop, None);
let _ = sdk.init_empty_session().await;
sdk.set_epoch(EpochString::new("3.0"));
sdk
Expand Down Expand Up @@ -38,13 +38,13 @@ async fn it_can_set_epoch() {
assert_eq!(sdk.current_epoch(), "3.0");
}

#[wasm_bindgen_test]
async fn it_can_deploy_contract() {
let mut sdk = init_sdk().await;
let tx = deploy_basic_contract(&mut sdk);
let expected = format!("0x{}", ClarityValue::Bool(true).serialize_to_hex().unwrap());
assert_eq!(tx.result, expected);
}
// #[wasm_bindgen_test]
// async fn it_can_deploy_contract() {
// let mut sdk = init_sdk().await;
// let tx = deploy_basic_contract(&mut sdk);
// let expected = format!("0x{}", ClarityValue::Bool(true).serialize_to_hex().unwrap());
// assert_eq!(tx.result, expected);
// }

// #[wasm_bindgen_test]
// async fn it_can_call_a_private_function() {
Expand Down
3 changes: 2 additions & 1 deletion components/clarinet-sdk/browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"readme": "./README.md",
"dependencies": {
"@hirosystems/clarinet-sdk-wasm-browser": "^2.11.2",
"@stacks/transactions": "^6.13.0"
"@stacks/transactions": "^6.13.0",
"sync-request": "^6.1.0"
}
}
4 changes: 3 additions & 1 deletion components/clarinet-sdk/browser/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import init, { SDK } from "@hirosystems/clarinet-sdk-wasm-browser";

import { httpClient } from "../../common/src/httpClient.js";

import { Simnet, getSessionProxy } from "./sdkProxy.js";
import { defaultVfs } from "./defaultVfs.js";

Expand All @@ -25,5 +27,5 @@ export const initSimnet = async (virtualFileSystem?: Function) => {
await init();

const vfs = virtualFileSystem ? virtualFileSystem : defaultVfs;
return new Proxy(new SDK(vfs), getSessionProxy()) as unknown as Simnet;
return new Proxy(new SDK(vfs, httpClient), getSessionProxy()) as unknown as Simnet;
};
11 changes: 11 additions & 0 deletions components/clarinet-sdk/common/src/httpClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import request, { HttpVerb, Options as HttpOptions } from "sync-request";

const encoder = new TextEncoder();

export function httpClient(method: HttpVerb, path: string, options?: HttpOptions): Uint8Array {
const response = request(method, path, options);
if (typeof response.body === "string") {
return encoder.encode(response.body);
}
return response.body;
}
1 change: 1 addition & 0 deletions components/clarinet-sdk/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"@stacks/transactions": "^6.13.0",
"kolorist": "^1.8.0",
"prompts": "^2.4.2",
"sync-request": "^6.1.0",
"vitest": "^1.6.0",
"yargs": "^17.7.2"
},
Expand Down
17 changes: 14 additions & 3 deletions components/clarinet-sdk/node/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export {
type Tx,
type TransferSTX,
} from "../../common/src/sdkProxyHelpers.js";
import { httpClient } from "../../common/src/httpClient.js";

import { vfs } from "./vfs.js";
import { Simnet, getSessionProxy } from "./sdkProxy.js";
Expand All @@ -22,6 +23,18 @@ BigInt.prototype.toJSON = function () {
return this.toString();
};

type Options = { trackCosts: boolean; trackCoverage: boolean };

export async function getSDK(options?: Options): Promise<Simnet> {
const module = await wasmModule;
let sdkOptions = new SDKOptions(!!options?.trackCosts, !!options?.trackCoverage);
const simnet = new Proxy(
new module.SDK(vfs, httpClient, sdkOptions),
getSessionProxy(),
) as unknown as Simnet;
return simnet;
}

// load wasm only once and memoize it
function memoizedInit() {
let simnet: Simnet | null = null;
Expand All @@ -32,9 +45,7 @@ function memoizedInit() {
options?: { trackCosts: boolean; trackCoverage: boolean },
) => {
if (noCache || !simnet) {
const module = await wasmModule;
let sdkOptions = new SDKOptions(!!options?.trackCosts, !!options?.trackCoverage);
simnet = new Proxy(new module.SDK(vfs, sdkOptions), getSessionProxy()) as unknown as Simnet;
simnet = await getSDK(options);
}

// start a new simnet session
Expand Down
43 changes: 43 additions & 0 deletions components/clarinet-sdk/node/tests/remote-data.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import fs from "node:fs";
import path from "node:path";
import { Cl } from "@stacks/transactions";
import { describe, expect, it, beforeEach, afterEach } from "vitest";

// test the built package and not the source code
// makes it simpler to handle wasm build
import { Simnet, getSDK, initSimnet, tx } from "..";

const deployerAddr = "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM";
const address1 = "ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5";
const address2 = "ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG";

let simnet: Simnet;

const deploymentPlanPath = path.join(
process.cwd(),
"tests/fixtures/deployments/default.simnet-plan.yaml",
);

function deleteExistingDeploymentPlan() {
if (fs.existsSync(deploymentPlanPath)) {
fs.unlinkSync(deploymentPlanPath);
}
}

beforeEach(async () => {
deleteExistingDeploymentPlan();
simnet = await getSDK();
await simnet.initEmtpySession();
});

afterEach(() => {
deleteExistingDeploymentPlan();
});

describe("simnet remote interactions", () => {
it("can call a remote contract", () => {
const r = simnet.execute("(+ 1 1)");
const result = simnet.callReadOnlyFn(`${address1}.counter2`, "one", [], address2);
expect(result.result).toStrictEqual(Cl.int(2));
});
});
2 changes: 2 additions & 0 deletions components/clarinet-sdk/node/vitest.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { defineConfig } from "vite";

export default defineConfig({
test: {
hookTimeout: 1000,
testTimeout: 1000,
// https://vitest.dev/guide/common-errors.html#failed-to-terminate-worker
pool: "forks",
poolOptions: {
Expand Down
2 changes: 1 addition & 1 deletion components/clarity-repl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ wasm-bindgen = { workspace = true, optional = true }
web-sys = { workspace = true, optional = true, features = ["XmlHttpRequest"]}

# DAP Debugger
tokio = { version = "1.35.1", features = ["full"], optional = true }
tokio = { version = "1.35.1", features = ["full"], optional = true}
tokio-util = { version = "0.7.10", features = ["codec"], optional = true }
futures = { version = "0.3.12", optional = true }
debug_types = { version = "1.0.0", optional = true }
Expand Down
3 changes: 3 additions & 0 deletions components/clarity-repl/src/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ extern crate prettytable;
#[macro_use]
extern crate hiro_system_kit;

#[macro_use]
mod uprint;

pub mod analysis;
pub mod frontend;
pub mod repl;
Expand Down
3 changes: 3 additions & 0 deletions components/clarity-repl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ extern crate serde_derive;
#[macro_use]
extern crate hiro_system_kit;

#[macro_use]
mod uprint;

pub mod analysis;

pub mod clarity {
Expand Down
Loading

0 comments on commit 0cf47fb

Please sign in to comment.