radix_clis/scrypto_bindgen/
mod.rs1use scrypto_bindgen::schema;
2use scrypto_bindgen::translation;
3use scrypto_bindgen::types;
4
5use clap::Parser;
6use radix_common::prelude::*;
7use radix_engine::system::system_db_reader::SystemDatabaseReader;
8use radix_substate_store_interface::interface::SubstateDatabase;
9use std::io::Write;
10
11use crate::resim::*;
12
13use self::schema::*;
14
15#[derive(Parser, Debug)]
17#[clap(author, version, about, long_about = None, name = "scrypto-bindgen")]
18pub struct Args {
19 package_address: String,
21
22 #[clap(short, long)]
25 reset_ledger: bool,
26
27 #[clap(short, long)]
28 func_sig_change: Vec<types::FunctionSignatureReplacementsInput>,
29}
30
31#[derive(Debug)]
32pub enum Error {
33 Bech32DecodeError(AddressBech32DecodeError),
34 PackageAddressError(ParsePackageAddressError),
35 ResimError(crate::resim::Error),
36 SchemaError(SchemaError),
37 IOError(std::io::Error),
38}
39
40pub fn run() -> Result<(), Error> {
41 let args = Args::parse();
42
43 let mut out = std::io::stdout();
45
46 let env = if args.reset_ledger {
47 SimulatorEnvironment::new_reset().map_err(Error::ResimError)?
48 } else {
49 SimulatorEnvironment::new().map_err(Error::ResimError)?
50 };
51 let db = env.db;
52
53 let blueprint_replacement_map = types::prepare_replacement_map(&args.func_sig_change);
54
55 let package_address = {
57 let (_, _, bytes) =
58 AddressBech32Decoder::validate_and_decode_ignore_hrp(&args.package_address)
59 .map_err(Error::Bech32DecodeError)?;
60 PackageAddress::try_from(bytes.as_slice()).map_err(Error::PackageAddressError)?
61 };
62
63 let bindings = {
65 let reader = SystemDatabaseReader::new(&db);
66 let definition = reader.get_package_definition(package_address);
67 let schema_resolver = SchemaResolver::new(package_address, &db);
68
69 let package_interface =
70 schema::package_interface_from_package_definition(definition, &schema_resolver)
71 .map_err(Error::SchemaError)?;
72 let mut ast_package_interface = translation::package_schema_interface_to_ast_interface(
73 package_interface,
74 package_address,
75 &schema_resolver,
76 &blueprint_replacement_map,
77 )
78 .map_err(Error::SchemaError)?;
79
80 ast_package_interface.auxiliary_types = Default::default();
82
83 ast_package_interface
84 };
85
86 writeln!(&mut out, "{}", quote::quote!(#bindings)).map_err(Error::IOError)?;
87
88 Ok(())
89}
90
91pub struct SchemaResolver<'s, S>(PackageAddress, SystemDatabaseReader<'s, S>)
92where
93 S: SubstateDatabase;
94
95impl<'s, S> SchemaResolver<'s, S>
96where
97 S: SubstateDatabase,
98{
99 pub fn new(node_id: PackageAddress, substate_database: &'s S) -> Self {
100 let reader = SystemDatabaseReader::new(substate_database);
101 Self(node_id, reader)
102 }
103}
104
105impl<'s, S> PackageSchemaResolver for SchemaResolver<'s, S>
106where
107 S: SubstateDatabase,
108{
109 fn lookup_schema(&self, schema_hash: &SchemaHash) -> Option<Rc<VersionedScryptoSchema>> {
110 self.1.get_schema(self.0.as_node_id(), schema_hash).ok()
111 }
112
113 fn resolve_type_kind(
114 &self,
115 type_identifier: &ScopedTypeId,
116 ) -> Result<LocalTypeKind<ScryptoCustomSchema>, schema::SchemaError> {
117 self.lookup_schema(&type_identifier.0)
118 .ok_or(schema::SchemaError::FailedToGetSchemaFromSchemaHash)?
119 .as_latest_version()
120 .ok_or(schema::SchemaError::FailedToGetSchemaFromSchemaHash)?
121 .resolve_type_kind(type_identifier.1)
122 .ok_or(schema::SchemaError::NonExistentLocalTypeIndex(
123 type_identifier.1,
124 ))
125 .cloned()
126 }
127
128 fn resolve_type_metadata(
129 &self,
130 type_identifier: &ScopedTypeId,
131 ) -> Result<TypeMetadata, schema::SchemaError> {
132 self.lookup_schema(&type_identifier.0)
133 .ok_or(schema::SchemaError::FailedToGetSchemaFromSchemaHash)?
134 .as_latest_version()
135 .ok_or(schema::SchemaError::FailedToGetSchemaFromSchemaHash)?
136 .resolve_type_metadata(type_identifier.1)
137 .ok_or(schema::SchemaError::NonExistentLocalTypeIndex(
138 type_identifier.1,
139 ))
140 .cloned()
141 }
142
143 fn resolve_type_validation(
144 &self,
145 type_identifier: &ScopedTypeId,
146 ) -> Result<TypeValidation<ScryptoCustomTypeValidation>, schema::SchemaError> {
147 self.lookup_schema(&type_identifier.0)
148 .ok_or(schema::SchemaError::FailedToGetSchemaFromSchemaHash)?
149 .as_latest_version()
150 .ok_or(schema::SchemaError::FailedToGetSchemaFromSchemaHash)?
151 .resolve_type_validation(type_identifier.1)
152 .ok_or(schema::SchemaError::NonExistentLocalTypeIndex(
153 type_identifier.1,
154 ))
155 .cloned()
156 }
157
158 fn package_address(&self) -> PackageAddress {
159 self.0
160 }
161}