Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feat/sign_and_send
Browse files Browse the repository at this point in the history
  • Loading branch information
willemneal committed Jul 8, 2024
2 parents 04d1358 + 40a1f1e commit e061785
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 30 deletions.
65 changes: 42 additions & 23 deletions cmd/crates/soroban-spec-typescript/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,29 +106,34 @@ pub fn generate(spec: &[ScSpecEntry]) -> String {
format!("{top}\n\n{bottom}")
}

fn doc_to_ts_doc(doc: &str, method: Option<&str>) -> String {
fn doc_to_ts_doc(doc: &str, method: Option<&str>, indent_level: usize) -> String {
let indent = " ".repeat(indent_level);
if let Some(method) = method {
let doc = if doc.is_empty() {
String::new()
} else {
format!(" *\n * {}", doc.split('\n').join("\n * "))
format!(
"\n{} * {}",
indent,
doc.split('\n').join(&format!("\n{indent} * "))
)
};
return format!(
r#"/**
* Construct and simulate a {method} transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.{doc}
*/"#
r#"{indent}/**
{indent} * Construct and simulate a {method} transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.{doc}
{indent} */"#
);
}

if doc.is_empty() {
return String::new();
}

let doc = doc.split('\n').join("\n * ");
let doc = doc.split('\n').join(&format!("\n{indent} * "));
format!(
r#"/**
* {doc}
*/
r#"{indent}/**
{indent} * {doc}
{indent} */
"#
)
}
Expand Down Expand Up @@ -188,7 +193,7 @@ pub fn entry_to_method_type(entry: &Entry) -> String {
)
})
.unwrap_or_default();
let doc = doc_to_ts_doc(doc, Some(name));
let doc = doc_to_ts_doc(doc, Some(name), 0);
let return_type = outputs_to_return_type(outputs);
format!(
r#"
Expand All @@ -199,7 +204,7 @@ pub fn entry_to_method_type(entry: &Entry) -> String {
}

Entry::Struct { doc, name, fields } => {
let docs = doc_to_ts_doc(doc, None);
let docs = doc_to_ts_doc(doc, None, 0);
let fields = fields.iter().map(field_to_ts).join("\n ");
format!(
r#"
Expand All @@ -211,13 +216,13 @@ pub fn entry_to_method_type(entry: &Entry) -> String {
}

Entry::TupleStruct { doc, name, fields } => {
let docs = doc_to_ts_doc(doc, None);
let docs = doc_to_ts_doc(doc, None, 0);
let fields = fields.iter().map(type_to_ts).join(", ");
format!("{docs}export type {name} = readonly [{fields}];")
}

Entry::Union { name, doc, cases } => {
let doc = doc_to_ts_doc(doc, None);
let doc = doc_to_ts_doc(doc, None, 0);
let cases = cases.iter().map(case_to_ts).join(" | ");

format!(
Expand All @@ -226,7 +231,7 @@ pub fn entry_to_method_type(entry: &Entry) -> String {
)
}
Entry::Enum { doc, name, cases } => {
let doc = doc_to_ts_doc(doc, None);
let doc = doc_to_ts_doc(doc, None, 0);
let cases = cases.iter().map(enum_case_to_ts).join("\n ");
let name = (name == "Error")
.then(|| format!("{name}s"))
Expand All @@ -239,16 +244,30 @@ pub fn entry_to_method_type(entry: &Entry) -> String {
)
}
Entry::ErrorEnum { doc, cases, .. } => {
let doc = doc_to_ts_doc(doc, None);
let doc = doc_to_ts_doc(doc, None, 0);
let cases = cases
.iter()
.map(|c| format!("{}: {{message:\"{}\"}}", c.value, c.doc))
.join(",\n ");
format!(
r#"{doc}export const Errors = {{
{cases}
}}"#
)
.enumerate()
.map(|(i, c)| {
if c.doc.is_empty() {
format!(
"{} {}: {{message:\"{}\"}}",
if i == 0 { "" } else { "\n" },
c.value,
c.name
)
} else {
format!(
"{}{} {}: {{message:\"{}\"}}",
if i == 0 { "" } else { "\n" },
doc_to_ts_doc(&c.doc, None, 1),
c.value,
c.name
)
}
})
.join(",\n");
format!("{doc}export const Errors = {{\n{cases}\n}}")
}
}
}
Expand All @@ -270,7 +289,7 @@ fn case_to_ts(case: &types::UnionCase) -> String {

fn field_to_ts(field: &types::StructField) -> String {
let types::StructField { doc, name, value } = field;
let doc = doc_to_ts_doc(doc, None);
let doc = doc_to_ts_doc(doc, None, 0);
let type_ = type_to_ts(value);
format!("{doc}{name}: {type_};")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,27 @@ pub struct Contract;

#[contracterror]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
/// Represents the different kinds of errors that can occur in the application.
pub enum Error {
/// The requested item was not found.
NotFound = 1,

/// The operation was not permitted.
NotPermitted = 2,

ClientDataJsonChallengeIncorrect = 3,
Secp256r1PublicKeyParse = 4,
Secp256r1SignatureParse = 5,
Secp256r1VerifyFailed = 6,
JsonParseError = 7,
InvalidContext = 8,
AlreadyInited = 9,
NotInited = 10,

/// An error occurred while parsing JSON.
JsonParseError = 4,

/// The provided context is invalid.
InvalidContext = 5,

/// The system has already been initialized.
AlreadyInited = 6,

/// The system has not been initialized yet.
NotInited = 7,
}

const SIGNERS: Symbol = symbol_short!("sigs");
Expand Down
7 changes: 7 additions & 0 deletions cmd/crates/soroban-test/tests/it/integration/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,11 @@ async fn invoke_test_bindings_context_failure() {
!content.contains("__check_auth"),
"Test failed: `__check_auth` found in src/index.ts"
);

// check enum message + doc working properly
assert!(
content.contains("The requested item was not found.")
&& content.contains("1: {message:\"NotFound\"}"),
r#"Test failed: Error enum not properly formatted in src/index.ts"#
);
}

0 comments on commit e061785

Please sign in to comment.