pop_common/
lib.rs

1// SPDX-License-Identifier: GPL-3.0
2
3#![doc = include_str!("../README.md")]
4
5use std::net::TcpListener;
6
7pub use account_id::{parse_account, parse_h160_account};
8pub use build::Profile;
9pub use errors::Error;
10pub use git::{Git, GitHub, Release};
11pub use helpers::{
12	get_project_name_from_path, get_relative_or_absolute_path, prefix_with_current_dir_if_needed,
13	replace_in_file,
14};
15pub use manifest::{add_crate_to_workspace, find_workspace_toml};
16pub use metadata::format_type;
17pub use signer::create_signer;
18pub use sourcing::set_executable_permission;
19pub use subxt::{Config, PolkadotConfig as DefaultConfig};
20pub use subxt_signer::sr25519::Keypair;
21pub use templates::extractor::extract_template_files;
22pub use test::test_project;
23
24/// Module for parsing and handling account IDs.
25pub mod account_id;
26/// Provides functionality for accessing rate-limited APIs.
27pub(crate) mod api;
28/// Provides build profiles for usage when building Rust projects.
29pub mod build;
30/// Represents the various errors that can occur in the crate.
31pub mod errors;
32/// Provides functionality for interacting with Git, GitHub, repositories and releases.
33pub mod git;
34/// Provides general purpose file and path helpers.
35pub mod helpers;
36/// Provides functionality for resolving and managing Cargo manifests.
37pub mod manifest;
38/// Provides functionality for formatting and resolving metadata types.
39pub mod metadata;
40/// Provides parsers for determining Polkadot SDK versions.
41pub mod polkadot_sdk;
42/// Provides functionality for creating a signer from a secret URI.
43pub mod signer;
44/// Provides functionality for sourcing binaries from a variety of different sources.
45pub mod sourcing;
46/// Provides traits and functions used for templates and template extraction.
47pub mod templates;
48/// Module for testing utilities and functionality.
49pub mod test;
50
51static APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));
52
53/// Trait for observing status updates.
54pub trait Status {
55	/// Update the observer with the provided `status`.
56	fn update(&self, status: &str);
57}
58
59impl Status for () {
60	// no-op: status updates are ignored
61	fn update(&self, _: &str) {}
62}
63
64/// Determines the target triple based on the current platform.
65pub fn target() -> Result<&'static str, Error> {
66	use std::env::consts::*;
67
68	if OS == "windows" {
69		return Err(Error::UnsupportedPlatform { arch: ARCH, os: OS });
70	}
71
72	match ARCH {
73		"aarch64" =>
74			return match OS {
75				"macos" => Ok("aarch64-apple-darwin"),
76				_ => Ok("aarch64-unknown-linux-gnu"),
77			},
78		"x86_64" | "x86" =>
79			return match OS {
80				"macos" => Ok("x86_64-apple-darwin"),
81				_ => Ok("x86_64-unknown-linux-gnu"),
82			},
83		&_ => {},
84	}
85	Err(Error::UnsupportedPlatform { arch: ARCH, os: OS })
86}
87
88/// Checks if preferred port is available, otherwise returns a random available port.
89pub fn find_free_port(preferred_port: Option<u16>) -> u16 {
90	// Try to bind to preferred port if provided.
91	if let Some(port) = preferred_port {
92		if TcpListener::bind(format!("127.0.0.1:{}", port)).is_ok() {
93			return port;
94		}
95	}
96
97	// Else, fallback to a random available port
98	TcpListener::bind("127.0.0.1:0")
99		.expect("Failed to bind to an available port")
100		.local_addr()
101		.expect("Failed to retrieve local address. This should never occur.")
102		.port()
103}
104
105/// Provides functionality for making calls to parachains or smart contracts.
106pub mod call {
107	// Note: cargo contract logic is used for parsing events after calling a chain. This could be
108	// refactored in the future so that we don't have to use cargo contract code in
109	// `pop-parachains`.
110	pub use contract_build::Verbosity;
111	pub use contract_extrinsics::{DisplayEvents, TokenMetadata};
112	pub use ink_env::DefaultEnvironment;
113}
114
115#[cfg(test)]
116mod tests {
117	use super::*;
118	use anyhow::Result;
119
120	#[test]
121	fn target_works() -> Result<()> {
122		use std::{process::Command, str};
123		let output = Command::new("rustc").arg("-vV").output()?;
124		let output = str::from_utf8(&output.stdout)?;
125		let target_expected = output
126			.lines()
127			.find(|l| l.starts_with("host: "))
128			.map(|l| &l[6..])
129			.unwrap()
130			.to_string();
131		assert_eq!(target()?, target_expected);
132		Ok(())
133	}
134
135	#[test]
136	fn find_free_port_works() -> Result<()> {
137		let port = find_free_port(None);
138		let addr = format!("127.0.0.1:{}", port);
139		// Constructs the TcpListener from the above port
140		let listener = TcpListener::bind(&addr);
141		assert!(listener.is_ok());
142		Ok(())
143	}
144}