nautilus-project / nautilus Goto Github PK
View Code? Open in Web Editor NEWSQL-native Solana program framework
Home Page: https://nautilus-project.vercel.app
License: Other
SQL-native Solana program framework
Home Page: https://nautilus-project.vercel.app
License: Other
I've started writing custom errors for Nautilus with the goal of making them very descriptive to help developers pinpoint problems in their code.
You can find all of Nautilus' custom errors here:
https://github.com/nautilus-project/nautilus/blob/main/solana/src/error.rs
Problem:
The error's implementation for Display
doesn't cause any program logs to emit on error thrown.
Instead, all you see is the u32
value returned with "Custom Program Error".
Although this is okay for now as an error on the client-side, the on-chain logs written using msg
under the impl fmt::Display
don't actually print in the program's logs when the error is invoked.
We should make sure those print whenever an error is encountered.
This issue is exactly the same as #21 but for the Python SDK.
Currently, you can create a Mint
or Token
using create(&self, ..)
but you can't do the standard operations on tokens, such as minTo
and transfer
.
We need to add these methods to the proper token traits so that users can perform these actions with tokens.
We also need to add these into the test suite.
Adding a Discriminator similar to how Anchor does into the first 8 bytes of the account would when creating a new record with Nautilus would make fetching (from gpa/geyser) easier as you could filter based on the accounts struct name.
I suggest that we use the exact same namespace as Anchor; global:Accountname.
Right now, there are two tests with pretty much all of the features Nautilus covers.
I'm suggesting making these more specific, meaning features such as Tokens, Records etc. have their own tests.
I've started writing custom errors for Nautilus with the goal of making them very descriptive to help developers pinpoint problems in their code.
You can find all of Nautilus' custom errors here:
https://github.com/nautilus-project/nautilus/blob/main/solana/src/error.rs
Problem:
Errors are not currently included in Nautilus' IDL.
Nautilus leverages one of the crates from Shank which allows it to parse the developer's crate and detect any structs, enums, errors, etc.
We should work to implement the following:
#[nautilus]
macroRight now there's some ordering hierarchy for accounts in the IDL, but it's partially involving alphabetical order for certain types of accounts.
It should be more predictable - likely based on the ordering of function signature parameters.
When you add default instructions to your struct, like so:
#[derive(nautilus::Table)]
#[default_instructions(
Create, Delete, Update
)]
struct Person {}
these instructions should automatically be written to the generated tokens & IDL
When you annotate a struct using #[derive(nautilus::Table)]
you can provide an attribute for any field to mark it as an authority using #[authority]
.
This means that the public key provided in this field must be a signer on any instruction that attempts to modify this record's data.
The code is uncompleted to actually add these checks, and you can find the skeleton code here:
https://github.com/nautilus-project/nautilus/blob/main/solana/syn/src/object/data.rs#L144
To close this issue, we need to:
#[authority]
to be of type Pubkey
count_authorities(..)
function to return the total count of authorities protecting that recordcheck_authorities(..)
function to validate that each specified authority for this record is marked as a signerFor context, the check_authorities(&self, accounts: Vec<AccountInfo>)
function takes a vector of AccountInfo
.
This function's parameters can be modified.
You'll find the code linked below where the actual AccountInfo
objects are read in from the provided accounts, and can choose to pipe them into this function in the most efficient way possible.
https://github.com/nautilus-project/nautilus/blob/main/solana/syn/src/entry/entry_variant.rs#L74
Make use of cargo expand
to see where the accounts are loaded and how they are used to initialize the objects declared in the user's function signature.
It might be a really cool idea to have some custom logging capabilities when writing Nautilus programs.
I've started a logging library similar to a diet Log4J for Solana programs here:
https://github.com/buffalojoec/splogger/blob/main/tests/impl_test.rs
I wonder if we can expand on this, make it really cool, and add it as an additional sub-crate for Nautilus. Thoughts?
The docs site renders from the Markdown files in the docs/md
folder.
It would be great to be able to group these Markdown files into subdirectories according to their section on the docs site.
For example, things under the "Basics" section could live in a docs/md/basics
directory.
As the docs grow, this would help with reducing clutter
Trying to run cargo build
inside solana
dir gives this output. Does this mean we need to update this version
here?
cargo build
Updating crates.io index
Updating git repository `https://github.com/nautilus-project/splogger`
error: failed to select a version for the requirement `solana-program = "^1.15.2"`
candidate versions found which didn't match: 1.14.18, 1.14.17, 1.14.16, ...
location searched: crates.io index
Currently you might be able to use Token2022 with Nautilus, but that wasn't considered in the design so far.
Best to get after this early, and incorporate Token & Token 2022 compatibility within all objects of the token
submodule - such as Mint
and Token
.
Ideally this implementation should follow some kind of dynamic interface, and the user should be easily able to configure which token program they want to use, or be able to support either (one-liner, plz).
The trait NautilusCreate<'_>
is primarily used to create new on-chain instances of Nautilus objects. However, I wrote separate traits for objects like Mint
, Metadata
, Token
, and so on.
We want to have a more standardized and dynamic way to add the methods create
and crate_with_payer
to any Nautilus object.
This would allow users to leverage create
and create_with_payer
for their objects - regardless of whether or not they're records, but it would also allow protocols across the Solana ecosystem to implement these dynamic traits to publish Nautilus libraries for their account data.
As of right now, having separate traits for token objects could be problematic for future account data types that aren't being implemented with either of Nautilus' derive macros.
Anchor makes use of a nice little function called into_inner()
which will convert an Account<'_, T>
into T
so you can work with the actual data type itself.
Nautilus should implement a similar function to access T
in a data type such as Record<'_, T>
or Account<'_, T>
Write a test suite that can calculate Lamport costs for things like compute units, rent, transaction fees, etc.
Basically, we want to get a detailed picture of the costs involved with choosing to build a program with Nautilus vs. Anchor vs. Native.
Right now, code snippets and blocks are rendered on the docs site as dark black text with a white background. They should instead render as a more traditional Markdown code block, like this:
use nautilus::*;
#[nautilus]
mod program_nautilus {
fn create_with_payer<'a>(
mut new_wallet: Create<'a, Wallet<'a>>,
rent_payer: Signer<Wallet<'a>>,
) -> ProgramResult {
new_wallet.create_with_payer(rent_payer)
}
}
I am willing to take this on, but if anyone wants to lend a hand, please do!
I've peppered the entire Rust codebase with comments and descriptions of what everything is doing, and very soon I'm going to create a video explaining exactly how the macros work and where to find the key ingredients.
Regardless, as we get closer to beta release, we're gonna need some docs!
Feel free to join me in grabbing anything worth covering in detail from the codebase and documenting it in the markdown files on the doc site: docs/md
I've started writing custom errors for Nautilus with the goal of making them very descriptive to help developers pinpoint problems in their code.
You can find all of Nautilus' custom errors here:
https://github.com/nautilus-project/nautilus/blob/main/solana/src/error.rs
Problem:
I'm not sure the way I've laid out this enum and it's associated traits & methods is the best practice for writing custom Solana Program Errors.
It would be a huge benefit to find some best practices or other implementations in project source code to re-write these errors into a much better implementation that makes proper use of ProgramError::Custom(u32)
.
Currently, the only type of PDA you're allowed to create using Nautilus is one that follows the table-record pattern, declared using the #[derive(nautilus::Table)]
macro.
When you set up a Nautilus Table, you don't provide the seeds. Nautilus will create them for you and manage your primary key according to your configuration for autoincrement
.
There are many use cases where developers may not want to use a table-record pattern for their object (PDA), they may instead want to treat it as an isolated instance of data.
We should provide eloquent support for this, by implementing the following functionality:
#[derive(nautilus::Object)]
Object<T>
NautilusIndex
as the records do, so it should not be required eitherNautilusData
trait
NautilusData
trait, such as primary_key(&self)
Currently Nautilus only supports the standard MetadataAccount
from Metaplex, and it doesn't even support all of the configurations yet either.
We should expand on the implementation to include all of the fields for MetadataAccount
and some new state objects, such as MasterEdition
This one might be a bit exploratory, but from what I can gather it makes sense to make zero-copy the default for interacting with the inner data of any account.
Considering Nautilus will add some light overhead code to your program, making zero-copy the default will definitely reduce compute for any Nautilus program, and will not put the onus on the user to try to use it.
In fact, it might be difficult to introduce a way for a user to leverage zero-copy or not, since it's all happening under the hood when they interact with objects.
I'm open to feedback on why this might be a bad idea, but ultimately I think it makes sense.
Right now we can create new on-chain instances of Nautilus objects, but we can't update the data once we've created it. This is for all types of objects, including tokens and records.
We need to build the traits to allow for updating of account data from Nautilus methods.
They are started here: https://github.com/nautilus-project/nautilus/blob/main/solana/src/objects/properties/_update.rs
These "Update" traits should adhere to whatever dynamic layout changes are introduced by #18 .
Right now, CPI is available through the structs themselves, but some use cases might require direct usage of CPIs.
We should make all CPIs public, add any necessary new ones for supported programs, and allow them to be consumed directly by users.
Inside the docs
folder is a NextJS app for Nautilus' main docs site.
This can be so much more than just a plain old docs site. Feel free to go in and spice things up a bit!
Get creative and have fun, and try to make something totally unique for Nautilus' docs, how-to's, and more.
Current way to get started using Nautilus is to do cargo init
and copy/paste one of the test sample.
It would be better to have a CLI command to create and configure the project accordingly
Nautilus is built with splogger
- a custom Solana program logger library - to give developers cool log formatting for their program logs.
In the tests
, it's being imported separately from use nautilus::*;
, but in reality it should probably just be included.
This is a pretty simple change in lib.rs
Nautilus' source layout has been in constant flux previously, but now things are shaping up to be more permanent.
Time to start laying down all the in-line Rust documentation for the crate for publishing.
Mints and Tokens can be PDAs on Solana. Currently Nautilus is not designed to support this.
Mints and Tokens should be able to be created as a PDA.
It would be great if somehow we could know whether or not it was created as a PDA so in the future we could direct how to CPI
We need to start building out the JavaScript SDK.
At the time of writing this issue, the JS SDK currently has a skeleton for initializing a Nautilus
instance and parsing SQL query strings.
Some of the skeleton shows how we can build this SDK, but I am open to proposed changes.
Problem:
The first step in the JavaScript SDK is going to be to take an IDL as input and create a TypeScript version of our program - similar to Anchor and Solita.
We can investigate using Anchor, Solita, or another existing tool to power this functionality, however I have the following requests:
.solitarc
, Anchor.toml
)shank
, solita
)We may also choose to write this functionality ourselves, and since JSON is closely related to JavaScript, this may not be too awful to do.
One thing worth mentioning: the Rust crate for the IDL currently has a POC build for converting JSON to TypeScript. We may decide that's an easier route to take rather than trying to import a JSON file to the SDK's Nautilus
instance.
I encourage draft PRs and Proof-of-Concepts
Solana Labs and ecosystem members have long been discussing an "IDL Standard" - which would basically impose an interface for all IDLs to adhere to, but allow them to implement their own additional configurations.
https://forum.solana.com/t/srfc-00008-idl-standard/66/8
Nautilus currently uses it's own IDL crate, which was by design so that it could leverage additional configs.
We should:
Option<T>
The idea here is to introduce a crate - for everyone across Solana to use - that allows you to create your own custom IDL that adheres to the interface.
Nautilus would then just use this crate within its source like any other project would.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.