metaplex-foundation / shank

Extracts IDL from Solana Rust contracts
https://docs.rs/crate/shank_macro/latest
118 stars 23 forks source link

feat: include errors in IDL #12

Closed thlorenz closed 2 years ago

thlorenz commented 2 years ago

Finds enums marked with thiserror Error derive and consume each error attribute on the respective variant to extract error information.

Supports explicit and implicit variant discriminants as well as a mix of both, some examples it handles:

Implicit Discriminants (Error codes)

/// Errors that may be returned by the Vault program.
#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)]
pub enum VaultError {
    /// Invalid instruction data passed in.
    #[error("Failed to unpack instruction data")]
    InstructionUnpackError,

    /// Lamport balance below rent-exempt threshold.
    #[error("Lamport balance below rent-exempt threshold")]
    NotRentExempt,
}

IDL:

{
  "version": "",
  "name": "",
  "instructions": [],
  "errors": [
    {
      "code": 0,
      "name": "InstructionUnpackError",
      "msg": "Failed to unpack instruction data"
    },
    {
      "code": 1,
      "name": "NotRentExempt",
      "msg": "Lamport balance below rent-exempt threshold"
    }
  ],
  "metadata": {
    "origin": "shank"
  }
}

Mixed Discriminants (Error Codes)

/// Errors that may be returned by the Vault program.
#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)]
pub enum VaultError {
    /// Invalid instruction data passed in.
    #[error("Failed to unpack instruction data")]
    InstructionUnpackError = 3000,

    /// Lamport balance below rent-exempt threshold.
    #[error("Lamport balance below rent-exempt threshold")]
    NotRentExempt,

    /// Already initialized
    #[error("Already initialized")]
    AlreadyInitialized,

    /// Uninitialized
    #[error("Uninitialized")]
    Uninitialized,

    /// Account does not have correct owner
    #[error("Account does not have correct owner")]
    IncorrectOwner = 4000,

    /// NumericalOverflowError
    #[error("NumericalOverflowError")]
    NumericalOverflowError,
}

IDL

{
  "version": "",
  "name": "",
  "instructions": [],
  "errors": [
    {
      "code": 3000,
      "name": "InstructionUnpackError",
      "msg": "Failed to unpack instruction data"
    },
    {
      "code": 3001,
      "name": "NotRentExempt",
      "msg": "Lamport balance below rent-exempt threshold"
    },
    {
      "code": 3002,
      "name": "AlreadyInitialized",
      "msg": "Already initialized"
    },
    {
      "code": 3003,
      "name": "Uninitialized",
      "msg": "Uninitialized"
    },
    {
      "code": 4000,
      "name": "IncorrectOwner",
      "msg": "Account does not have correct owner"
    },
    {
      "code": 4001,
      "name": "NumericalOverflowError",
      "msg": "NumericalOverflowError"
    }
  ],
  "metadata": {
    "origin": "shank"
  }
}

Improvements

To extract correct error codes ParsedEnum was improved to handle multiple discriminant scenarios.

FIXES: https://github.com/metaplex-foundation/metaplex-program-library/issues/261