1#![doc = include_str!("../README.md")]
4
5pub use account_id::{parse_account, parse_h160_account};
6#[cfg(feature = "integration-tests")]
7#[allow(deprecated)]
8use assert_cmd::cargo::cargo_bin;
9pub use build::Profile;
10pub use errors::Error;
11pub use git::{Git, GitHub, Release};
12pub use helpers::{get_project_name_from_path, get_relative_or_absolute_path, replace_in_file};
13pub use metadata::format_type;
14pub use signer::create_signer;
15pub use sourcing::set_executable_permission;
16use std::{cmp::Ordering, net::TcpListener, ops::Deref};
17#[cfg(feature = "integration-tests")]
18use std::{ffi::OsStr, path::Path};
19pub use subxt::{Config, PolkadotConfig as DefaultConfig};
20pub use subxt_signer::sr25519::Keypair;
21pub use templates::{
22 extractor::extract_template_files,
23 frontend::{FrontendTemplate, FrontendType},
24};
25pub use test::test_project;
26
27pub mod account_id;
29pub(crate) mod api;
31pub mod build;
33pub mod errors;
35pub mod git;
37pub mod helpers;
39pub mod manifest;
41pub mod metadata;
43pub mod polkadot_sdk;
45pub mod signer;
47pub mod sourcing;
49pub mod templates;
51pub mod test;
53pub mod test_env;
55
56static APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));
57
58pub trait Status {
60 fn update(&self, status: &str);
62}
63
64impl Status for () {
65 fn update(&self, _: &str) {}
67}
68
69pub fn target() -> Result<&'static str, Error> {
71 use std::env::consts::*;
72
73 if OS == "windows" {
74 return Err(Error::UnsupportedPlatform { arch: ARCH, os: OS });
75 }
76
77 match ARCH {
78 "aarch64" => {
79 return match OS {
80 "macos" => Ok("aarch64-apple-darwin"),
81 _ => Ok("aarch64-unknown-linux-gnu"),
82 };
83 },
84 "x86_64" | "x86" => {
85 return match OS {
86 "macos" => Ok("x86_64-apple-darwin"),
87 _ => Ok("x86_64-unknown-linux-gnu"),
88 };
89 },
90 &_ => {},
91 }
92 Err(Error::UnsupportedPlatform { arch: ARCH, os: OS })
93}
94
95#[cfg(feature = "integration-tests")]
106pub fn pop(
107 dir: &Path,
108 args: impl IntoIterator<Item = impl AsRef<OsStr>>,
109) -> tokio::process::Command {
110 #[allow(deprecated)]
111 let mut command = tokio::process::Command::new(cargo_bin("pop"));
112 command.current_dir(dir).args(args);
113 println!("{command:?}");
114 command
115}
116
117pub fn find_free_port(preferred_port: Option<u16>) -> u16 {
119 if let Some(port) = preferred_port &&
121 TcpListener::bind(format!("127.0.0.1:{}", port)).is_ok()
122 {
123 return port;
124 }
125
126 TcpListener::bind("127.0.0.1:0")
128 .expect("Failed to bind to an available port")
129 .local_addr()
130 .expect("Failed to retrieve local address. This should never occur.")
131 .port()
132}
133
134pub struct SortedSlice<'a, T>(&'a mut [T]);
136impl<'a, T> SortedSlice<'a, T> {
137 pub fn by(slice: &'a mut [T], f: impl FnMut(&T, &T) -> Ordering) -> Self {
143 slice.sort_by(f);
144 Self(slice)
145 }
146
147 pub fn by_key<K: Ord>(slice: &'a mut [T], f: impl FnMut(&T) -> K) -> Self {
154 slice.sort_by_key(f);
155 Self(slice)
156 }
157}
158
159impl<T> Deref for SortedSlice<'_, T> {
160 type Target = [T];
161
162 fn deref(&self) -> &Self::Target {
163 &self.0[..]
164 }
165}
166
167pub mod call {
169 pub use contract_build::Verbosity;
173 pub use contract_extrinsics::{DisplayEvents, TokenMetadata};
174 pub use ink_env::DefaultEnvironment;
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180 use anyhow::Result;
181
182 #[test]
183 fn target_works() -> Result<()> {
184 use std::{process::Command, str};
185 let output = Command::new("rustc").arg("-vV").output()?;
186 let output = str::from_utf8(&output.stdout)?;
187 let target_expected = output
188 .lines()
189 .find(|l| l.starts_with("host: "))
190 .map(|l| &l[6..])
191 .unwrap()
192 .to_string();
193 assert_eq!(target()?, target_expected);
194 Ok(())
195 }
196
197 #[test]
198 fn find_free_port_works() -> Result<()> {
199 let port = find_free_port(None);
200 let addr = format!("127.0.0.1:{}", port);
201 let listener = TcpListener::bind(&addr);
203 assert!(listener.is_ok());
204 Ok(())
205 }
206
207 #[test]
208 fn sorted_slice_sorts_by_function() {
209 let mut values = ["one", "two", "three"];
210 let sorted = SortedSlice::by(values.as_mut_slice(), |a, b| a.cmp(b));
211 assert_eq!(*sorted, ["one", "three", "two"]);
212 }
213
214 #[test]
215 fn sorted_slice_sorts_by_key() {
216 let mut values = ['c', 'b', 'a'];
217 let sorted = SortedSlice::by_key(values.as_mut_slice(), |v| *v as u8);
218 assert_eq!(*sorted, ['a', 'b', 'c']);
219 }
220}