From f44886d769f9af92a04056587d2876cc8a3daa51 Mon Sep 17 00:00:00 2001
From: "valdo.carbonaboyz.stark" <valentin@pupucecorp.com>
Date: Thu, 21 Nov 2024 22:03:47 +0100
Subject: [PATCH] feat: add i128 + use BigNumberish type (#2705)

* feat: add i128 + use BigNumberish type

* fix: move string declarations to variables
---
 .../plugins/typescript/generator/constants.rs | 16 +++++
 .../plugins/typescript/generator/function.rs  | 12 ++--
 .../plugins/typescript/generator/interface.rs | 12 +++-
 .../src/plugins/typescript/generator/mod.rs   | 61 +++++++++++--------
 4 files changed, 67 insertions(+), 34 deletions(-)
 create mode 100644 crates/dojo/bindgen/src/plugins/typescript/generator/constants.rs

diff --git a/crates/dojo/bindgen/src/plugins/typescript/generator/constants.rs b/crates/dojo/bindgen/src/plugins/typescript/generator/constants.rs
new file mode 100644
index 0000000000..24f3dc3772
--- /dev/null
+++ b/crates/dojo/bindgen/src/plugins/typescript/generator/constants.rs
@@ -0,0 +1,16 @@
+pub const CAIRO_FELT252: &str = "felt252";
+pub const CAIRO_CONTRACT_ADDRESS: &str = "ContractAddress";
+pub const CAIRO_BYTE_ARRAY: &str = "ByteArray";
+pub const CAIRO_U8: &str = "u8";
+pub const CAIRO_U16: &str = "u16";
+pub const CAIRO_U32: &str = "u32";
+pub const CAIRO_U64: &str = "u64";
+pub const CAIRO_U128: &str = "u128";
+pub const CAIRO_U256: &str = "u256";
+pub const CAIRO_U256_STRUCT: &str = "U256";
+pub const CAIRO_I128: &str = "i128";
+pub const CAIRO_BOOL: &str = "bool";
+
+pub const JS_BOOLEAN: &str = "boolean";
+pub const JS_STRING: &str = "string";
+pub const JS_BIGNUMBERISH: &str = "BigNumberish";
diff --git a/crates/dojo/bindgen/src/plugins/typescript/generator/function.rs b/crates/dojo/bindgen/src/plugins/typescript/generator/function.rs
index 321f971806..c30cf4ff57 100644
--- a/crates/dojo/bindgen/src/plugins/typescript/generator/function.rs
+++ b/crates/dojo/bindgen/src/plugins/typescript/generator/function.rs
@@ -2,6 +2,7 @@ use cainome::parser::tokens::{CompositeType, Function, Token};
 use convert_case::{Case, Casing};
 use dojo_world::contracts::naming;
 
+use super::constants::JS_BIGNUMBERISH;
 use super::JsType;
 use crate::error::BindgenResult;
 use crate::plugins::{BindgenContractGenerator, Buffer};
@@ -12,7 +13,8 @@ impl TsFunctionGenerator {
     fn check_imports(&self, buffer: &mut Buffer) {
         if !buffer.has("import { DojoProvider } from ") {
             buffer.insert(0, "import { DojoProvider } from \"@dojoengine/core\";".to_owned());
-            buffer.insert(1, "import { Account } from \"starknet\";".to_owned());
+            buffer
+                .insert(1, format!("import {{ Account, {} }} from \"starknet\";", JS_BIGNUMBERISH));
             buffer.insert(2, "import * as models from \"./models.gen\";\n".to_owned());
         }
     }
@@ -235,8 +237,8 @@ mod tests {
     fn test_generate_system_function() {
         let generator = TsFunctionGenerator {};
         let function = create_change_theme_function();
-        let expected = "\tconst actions_changeTheme = async (snAccount: Account, value: number) \
-                        => {
+        let expected = "\tconst actions_changeTheme = async (snAccount: Account, value: \
+                        BigNumberish) => {
 \t\ttry {
 \t\t\treturn await provider.execute(
 \t\t\t\tsnAccount,
@@ -268,7 +270,7 @@ mod tests {
     fn test_format_function_inputs() {
         let generator = TsFunctionGenerator {};
         let function = create_change_theme_function();
-        let expected = "snAccount: Account, value: number";
+        let expected = "snAccount: Account, value: BigNumberish";
         assert_eq!(expected, generator.format_function_inputs(&function))
     }
 
@@ -276,7 +278,7 @@ mod tests {
     fn test_format_function_inputs_complex() {
         let generator = TsFunctionGenerator {};
         let function = create_change_theme_function();
-        let expected = "snAccount: Account, value: number";
+        let expected = "snAccount: Account, value: BigNumberish";
         assert_eq!(expected, generator.format_function_inputs(&function))
     }
 
diff --git a/crates/dojo/bindgen/src/plugins/typescript/generator/interface.rs b/crates/dojo/bindgen/src/plugins/typescript/generator/interface.rs
index f75efadf94..111a082d3c 100644
--- a/crates/dojo/bindgen/src/plugins/typescript/generator/interface.rs
+++ b/crates/dojo/bindgen/src/plugins/typescript/generator/interface.rs
@@ -4,14 +4,20 @@ use super::JsType;
 use crate::error::BindgenResult;
 use crate::plugins::{BindgenModelGenerator, Buffer};
 
+const BIGNUMNERISH_IMPORT: &str = "import type { BigNumberish } from 'starknet';";
+
 pub(crate) struct TsInterfaceGenerator;
 
 impl BindgenModelGenerator for TsInterfaceGenerator {
-    fn generate(&self, token: &Composite, _buffer: &mut Buffer) -> BindgenResult<String> {
+    fn generate(&self, token: &Composite, buffer: &mut Buffer) -> BindgenResult<String> {
         if token.r#type != CompositeType::Struct || token.inners.is_empty() {
             return Ok(String::new());
         }
 
+        if !buffer.has(BIGNUMNERISH_IMPORT) {
+            buffer.push(BIGNUMNERISH_IMPORT.to_owned());
+        }
+
         Ok(format!(
             "// Type definition for `{path}` struct
 export interface {name} {{
@@ -82,8 +88,8 @@ mod tests {
         assert_eq!(
             result,
             "// Type definition for `core::test::TestStruct` struct\nexport interface TestStruct \
-             {\n\tfieldOrder: string[];\n\tfield1: number;\n\tfield2: number;\n\tfield3: \
-             number;\n}\n"
+             {\n\tfieldOrder: string[];\n\tfield1: BigNumberish;\n\tfield2: \
+             BigNumberish;\n\tfield3: BigNumberish;\n}\n"
         );
     }
 
diff --git a/crates/dojo/bindgen/src/plugins/typescript/generator/mod.rs b/crates/dojo/bindgen/src/plugins/typescript/generator/mod.rs
index 2c33e067c2..49978627fe 100644
--- a/crates/dojo/bindgen/src/plugins/typescript/generator/mod.rs
+++ b/crates/dojo/bindgen/src/plugins/typescript/generator/mod.rs
@@ -1,6 +1,12 @@
 use cainome::parser::tokens::{Composite, Token};
+use constants::{
+    CAIRO_BOOL, CAIRO_BYTE_ARRAY, CAIRO_CONTRACT_ADDRESS, CAIRO_FELT252, CAIRO_I128, CAIRO_U128,
+    CAIRO_U16, CAIRO_U256, CAIRO_U256_STRUCT, CAIRO_U32, CAIRO_U64, CAIRO_U8, JS_BIGNUMBERISH,
+    JS_BOOLEAN, JS_STRING,
+};
 use convert_case::{Case, Casing};
 
+pub(crate) mod constants;
 pub(crate) mod r#enum;
 pub(crate) mod erc;
 pub(crate) mod function;
@@ -54,17 +60,18 @@ pub(crate) struct JsType(String);
 impl From<&str> for JsType {
     fn from(value: &str) -> Self {
         match value {
-            "felt252" => JsType("number".to_owned()),
-            "ContractAddress" => JsType("string".to_owned()),
-            "ByteArray" => JsType("string".to_owned()),
-            "u8" => JsType("number".to_owned()),
-            "u16" => JsType("number".to_owned()),
-            "u32" => JsType("number".to_owned()),
-            "u64" => JsType("number".to_owned()),
-            "u128" => JsType("number".to_owned()),
-            "u256" => JsType("number".to_owned()),
-            "U256" => JsType("number".to_owned()),
-            "bool" => JsType("boolean".to_owned()),
+            CAIRO_FELT252 => JsType(JS_BIGNUMBERISH.to_owned()),
+            CAIRO_CONTRACT_ADDRESS => JsType(JS_STRING.to_owned()),
+            CAIRO_BYTE_ARRAY => JsType(JS_STRING.to_owned()),
+            CAIRO_U8 => JsType(JS_BIGNUMBERISH.to_owned()),
+            CAIRO_U16 => JsType(JS_BIGNUMBERISH.to_owned()),
+            CAIRO_U32 => JsType(JS_BIGNUMBERISH.to_owned()),
+            CAIRO_U64 => JsType(JS_BIGNUMBERISH.to_owned()),
+            CAIRO_U128 => JsType(JS_BIGNUMBERISH.to_owned()),
+            CAIRO_U256 => JsType(JS_BIGNUMBERISH.to_owned()),
+            CAIRO_U256_STRUCT => JsType(JS_BIGNUMBERISH.to_owned()),
+            CAIRO_I128 => JsType(JS_BIGNUMBERISH.to_owned()),
+            CAIRO_BOOL => JsType(JS_BOOLEAN.to_owned()),
             _ => JsType(value.to_owned()),
         }
     }
@@ -102,17 +109,18 @@ pub(crate) struct JsDefaultValue(String);
 impl From<&str> for JsDefaultValue {
     fn from(value: &str) -> Self {
         match value {
-            "felt252" => JsDefaultValue("0".to_string()),
-            "ContractAddress" => JsDefaultValue("\"\"".to_string()),
-            "ByteArray" => JsDefaultValue("\"\"".to_string()),
-            "u8" => JsDefaultValue("0".to_string()),
-            "u16" => JsDefaultValue("0".to_string()),
-            "u32" => JsDefaultValue("0".to_string()),
-            "u64" => JsDefaultValue("0".to_string()),
-            "u128" => JsDefaultValue("0".to_string()),
-            "u256" => JsDefaultValue("0".to_string()),
-            "U256" => JsDefaultValue("0".to_string()),
-            "bool" => JsDefaultValue("false".to_string()),
+            CAIRO_FELT252 => JsDefaultValue("0".to_string()),
+            CAIRO_CONTRACT_ADDRESS => JsDefaultValue("\"\"".to_string()),
+            CAIRO_BYTE_ARRAY => JsDefaultValue("\"\"".to_string()),
+            CAIRO_U8 => JsDefaultValue("0".to_string()),
+            CAIRO_U16 => JsDefaultValue("0".to_string()),
+            CAIRO_U32 => JsDefaultValue("0".to_string()),
+            CAIRO_U64 => JsDefaultValue("0".to_string()),
+            CAIRO_U128 => JsDefaultValue("0".to_string()),
+            CAIRO_U256 => JsDefaultValue("0".to_string()),
+            CAIRO_U256_STRUCT => JsDefaultValue("0".to_string()),
+            CAIRO_I128 => JsDefaultValue("0".to_string()),
+            CAIRO_BOOL => JsDefaultValue("false".to_string()),
             _ => JsDefaultValue(value.to_string()),
         }
     }
@@ -175,6 +183,7 @@ mod tests {
         Tuple,
     };
 
+    use crate::plugins::typescript::generator::constants::JS_BIGNUMBERISH;
     use crate::plugins::typescript::generator::{generate_type_init, JsDefaultValue, JsType};
 
     impl PartialEq<JsType> for &str {
@@ -192,13 +201,13 @@ mod tests {
     #[test]
     fn test_js_type_basics() {
         assert_eq!(
-            "number",
+            JS_BIGNUMBERISH,
             JsType::from(&Token::CoreBasic(CoreBasic {
                 type_path: "core::integer::u8".to_owned()
             }))
         );
         assert_eq!(
-            "number",
+            JS_BIGNUMBERISH,
             JsType::from(&Token::CoreBasic(CoreBasic { type_path: "core::felt252".to_owned() }))
         )
     }
@@ -206,7 +215,7 @@ mod tests {
     #[test]
     fn test_tuple_type() {
         assert_eq!(
-            "[number, number]",
+            format!("[{}, {}]", JS_BIGNUMBERISH, JS_BIGNUMBERISH).as_str(),
             JsType::from(&Token::Tuple(Tuple {
                 type_path: "(core::integer::u8,core::integer::u128)".to_owned(),
                 inners: vec![
@@ -220,7 +229,7 @@ mod tests {
     #[test]
     fn test_array_type() {
         assert_eq!(
-            "Array<[number, number]>",
+            format!("Array<[{}, {}]>", JS_BIGNUMBERISH, JS_BIGNUMBERISH).as_str(),
             JsType::from(&Token::Array(Array {
                 type_path: "core::array::Span<(core::integer::u8,core::integer::u128)>".to_owned(),
                 inner: Box::new(Token::Tuple(Tuple {