Skip to content

Commit

Permalink
Merge pull request #85 from Web3-Builders-Alliance/main
Browse files Browse the repository at this point in the history
  • Loading branch information
JuanMarchetto authored Jun 25, 2023
2 parents 3b398ee + 1f0aec4 commit cf9f28a
Show file tree
Hide file tree
Showing 70 changed files with 6,836 additions and 648 deletions.
29 changes: 13 additions & 16 deletions README.MD
Original file line number Diff line number Diff line change
@@ -1,39 +1,36 @@
# SODA: Ship a Solana program inferred from Solana data.

A tool for Solana development and audit that allows you to automate tasks and build Solana programs and clients from: IDLs, on-chain data, existing repos, input and output examples of each instruction, and naming conventions, among other possible resources.
From IDL to whatever you want.

### First Version Features
From an IDL to whatever you want.

### Current Features

- **Generate Solana Program and client from IDL.**
- **Write, read and edit IDL in a desktop UI.**
- **Template based: create your custom building blocks.**
- **Lang and chain agnostic.**
- **Compatibility with Anchor.**

## Getting Started

This is a tool that can read an IDL and outputs the files needed for a Solana program and client code. Current default template outputs an Anchor-Workspace and a NEXT.js, Typescript and Tailwind client.
## Install Soda CLI

Do you prefer a different client? the program code in other language? write a template and all your projects can generate from it.
You can install the CLI using cargo or npm.

- Using cargo:
`cargo install soda-cli`

***
- Using npm:
`npm i @use_soda/soda-cli`

#### Steps to run this project
## Install Soda Desktop

0. prerrequisites: rust, node
1. to run desktop program `cd ui/cargo tauri dev`
2. to run cli `cd cli` and follow usage instrutions bellow
To install the Desktop App you need to [download the lastest release](https://github.com/Web3-Builders-Alliance/soda/releases)

#### CLI Usage

`soda`: from ./idl.json generates code using default template.
`soda-cli`: from ./idl.json generates code using default template.

`soda <path>` from idl file or url in `<path>` generate project using default template.
`soda-cli <path>` from idl file or url in `<path>` generate project using default template.

`soda <path1> <path2>` from idl file or url in `<path1>` generate project using template in `<path2>`.
`soda-cli <path1> <path2>` from idl file or url in `<path1>` generate project using template in `<path2>`.

## Note

Expand Down
20 changes: 10 additions & 10 deletions cli/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
[package]
name = "soda-cli"
version = "0.1.0"
version = "0.0.1"
edition = "2021"
license = "Apache-2.0"
description = "Generates Solana Projects from an IDL"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
serde_json = "1.0.93"
env_logger = "0.10"
clap = { version = "4.1.8", features = ["derive"] }
soda = { path = "../crate" }
soda_sol = { path = "../crate" }
25 changes: 25 additions & 0 deletions cli/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "@use_soda/soda-cli",
"version": "0.0.1",
"description": "Generates Solana Projects from an IDL",
"main": "start.js",
"directories": {
"test": "tests"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"postinstall": "node ./pre-install.js",
"uninstall": "node ./uninstall.js"
},
"keywords": [],

"license": "Apache-2.0",
"files": [
"pre-install.js",
"start.js",
"uninstall.js",
"README.md",
"LICENSE"
]
}

42 changes: 42 additions & 0 deletions cli/pre-install.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env node

const fs = require("fs");
const path = require("path");
const { exec } = require("child_process");
const { homedir } = require("os");

const cargoDir = path.join(homedir(), ".cargo");

// check if directory exists
if (fs.existsSync(cargoDir)) {
// console.log("Cargo found.");
} else {
const setCargo = 'PATH="/$HOME/.cargo/bin:${PATH}"';
console.log("Installing deps [cargo].");

exec(
`curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && ${setCargo}`,
(error) => {
if (error) {
console.log(
"curl failed! Curl may not be installed on the OS. View https://curl.se/download.html to install."
);
console.log(error);
}
}
);
}

const features = process.env.npm_config_features ? `--features ${process.env.npm_config_features.replace(",", " ")}` : "";

console.log(`Installing and compiling soda-cli 0.0.1 ${features} ...`);
exec(`cargo install soda-cli --vers 0.0.1 ${features}`, (error, stdout, stderr) => {
console.log(stdout);
if (error || stderr) {
console.log(error || stderr);
} else {
console.log("install finished!");
}
});


2 changes: 1 addition & 1 deletion cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![allow(non_snake_case, non_camel_case_types)]
use clap::Parser;
use soda::{generate_from_idl, IDL};
use soda_sol::{generate_from_idl, IDL};
use std::error::Error;
use std::fs::{canonicalize, File};

Expand Down
23 changes: 23 additions & 0 deletions cli/start.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env node

const { exec } = require("child_process");

const controller = typeof AbortController !== "undefined" ? new AbortController() : { abort: () => {}, signal: typeof AbortSignal !== "undefined" ? new AbortSignal() : undefined };
const { signal } = controller;

exec("soda-cli", { signal }, (error, stdout, stderr) => {
stdout && console.log(stdout);
stderr && console.error(stderr);
if (error !== null) {
console.log(`exec error: ${error}`);
}
});

process.on("SIGTERM", () => {
controller && controller.abort();
});

process.on("SIGINT", () => {
controller && controller.abort();
});

44 changes: 44 additions & 0 deletions cli/uninstall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env node

const fs = require("fs");
const path = require("path");
const { exec } = require("child_process");
const { homedir } = require("os");

const cargoDir = path.join(homedir(), ".cargo");

// check if directory exists
if (fs.existsSync(cargoDir)) {
// console.log("Cargo found.");
} else {
const setCargo = 'PATH="/$HOME/.cargo/bin:${PATH}"';
console.log("Installing deps [cargo].");

exec(
`curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && ${setCargo}`,
(error) => {
if (error) {
console.log(
"curl failed! Curl may not be installed on the OS. View https://curl.se/download.html to install."
);
console.log(error);
}
}
);
}

const binp = path.join(cargoDir, "bin", "soda-cli");

if (fs.existsSync(binp)) {
console.log("Uninstalling soda-cli...");
exec(`cargo uninstall soda-cli`, (error, stdout, stderr) => {
console.log(stdout);
if (error || stderr) {
console.log(error || stderr);
}
});
} else {
console.log("soda-cli not found skipping!");
}


4 changes: 2 additions & 2 deletions crate/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions crate/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
[package]
name = "soda"
version = "0.1.0"
name = "soda_sol"
version = "0.0.3"
edition = "2021"
license = "Apache-2.0"
description = "Generates Solana Projects from an IDL"
repository = "https://github.com/Web3-Builders-Alliance/soda"
authors = ["Juan Patricio Marchetto"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand Down
35 changes: 14 additions & 21 deletions crate/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::structs;
use handlebars::{handlebars_helper, Handlebars};
use structs::{InstructionType, InstructionTypeVec, VecEnum, IDL};
use walkdir::WalkDir;
use structs::{InstructionType, InstructionTypeVec, TemplateHelper, VecEnum, IDL};

pub(crate) fn create_handlebars_registry() -> Handlebars<'static> {
handlebars_helper!(snakecase: |name: String| name.chars().fold(
Expand All @@ -16,10 +15,14 @@ pub(crate) fn create_handlebars_registry() -> Handlebars<'static> {

handlebars_helper!(pascalcase: |name: String|{
let mut passcalcaseChars: Vec<char> = name.chars().collect();
if passcalcaseChars.is_empty() {
"".to_string()
} else {
let first: Vec<char> = passcalcaseChars[0].to_uppercase().to_string().chars().collect();
passcalcaseChars[0] = *first.first().unwrap();
let passcalcase: String = passcalcaseChars.into_iter().collect();
passcalcase
}
}
);

Expand Down Expand Up @@ -55,24 +58,14 @@ pub(crate) fn create_handlebars_registry() -> Handlebars<'static> {
handlebars
}

pub fn apply_user_helpers(template_path: &str, handlebars: &mut handlebars::Handlebars) {
for entry in WalkDir::new(format!("{}/helpers/", template_path)) {
match entry {
Ok(val) => {
let path = format!("{}", val.path().to_string_lossy());
if path.split('.').count() > 1 {
let helper_name = path
.get(0..path.len() - 5)
.unwrap()
.split('/')
.last()
.unwrap();
handlebars
.register_script_helper_file(helper_name, &path)
.unwrap();
}
}
Err(err) => println!("{}", err),
}
pub fn apply_user_helpers(helpers: Vec<TemplateHelper>, handlebars: &mut handlebars::Handlebars) {
for TemplateHelper {
helper_name,
script,
} in helpers
{
handlebars
.register_script_helper(&helper_name, &script)
.unwrap();
}
}
Loading

0 comments on commit cf9f28a

Please sign in to comment.