• Stars
    star
    115
  • Rank 305,916 (Top 7 %)
  • Language
    TypeScript
  • License
    Apache License 2.0
  • Created almost 3 years ago
  • Updated 12 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Genrates an SDK API from solana contract IDL.

solita Build Lint and Test Solita

Sol ana I DL t o A PI generator.

solita-logo

Table of Contents generated with DocToc

How does it Work?

Solita generates a low level TypeScript SDK for your Solana Rust programs from the IDL extracted by anchor or shank.

In order to use solita with shank do the following:

  • add the shank library to your Rust project via cargo add shank
  • annotate your Rust program as outlined here
  • add solita to the dev dependencies of your SDK package via yarn add -D @metaplex-foundation/solita
  • add a config similar to the below into .solitarc.js in your SDK package root
const path = require('path');
const programDir = path.join(__dirname, '..', 'program');
const idlDir = path.join(__dirname, 'idl');
const sdkDir = path.join(__dirname, 'src', 'generated');
const binaryInstallDir = path.join(__dirname, '.crates');

module.exports = {
  idlGenerator: 'shank',
  programName: 'mpl_token_vault',
  idlDir,
  sdkDir,
  binaryInstallDir,
  programDir,
};

Now running yarn solita from the same folder will take care of installing the matching shank binary and generating the IDL and SDK.

Run it each time you make a change to your program to generate the TypeScript SDK.

Since we're writing the shank binary to .crates/ you should add that folder to your .gitignore.

Full Example: Token Metadata Solita + Shank Setup

In order to use solita with anchor do the following:

  • annotate your Rust program with anchor attributes
  • add solita to the dev dependencies of your SDK package via yarn add -D @metaplex-foundation/solita
  • add a config similar to the below into .solitarc.js in your SDK package root
const path = require('path');
const programDir = path.join(__dirname, '..', 'program');
const idlDir = path.join(__dirname, 'idl');
const sdkDir = path.join(__dirname, 'src', 'generated');
const binaryInstallDir = path.join(__dirname, '.crates');

module.exports = {
  idlGenerator: 'anchor',
  programName: 'auction_house',
  programId: 'hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk',
  idlDir,
  sdkDir,
  binaryInstallDir,
  programDir,
};

Now running yarn solita from the same folder will take care of installing the matching anchor binary and generating the IDL and SDK.

Run it each time you make a change to your program to generate the TypeScript SDK.

Since we're writing the anchor binary to .crates/ you should add that folder to your .gitignore.

NOTE: that for anchor generated IDL an optional anchorRemainingAccounts property is added to each set of instruction accounts. If your programs are not using those you can specifically turn that off by setting anchorRemainingAccounts: false.

Full Example: MPL Candy Machine Solita + Anchor Setup

Type Aliases

In order to have Solita resolve specific types to a Rust builtin type please provide a type alias map as in the below config. Solita then will treat those as if they were the aliased type.

module.exports = {
  idlGenerator: 'anchor',
  [ .. ]
  typeAliases: {
    UnixTimestamp: 'i64'
  }
};

Custom De/Serializers

For some accounts the generated de/serializers don't work. In those cases a custom de/serializer can be specified.

This is as simple as adding a module to your project which exports a either or both of the below functions:

export function deserialize(buf: Buffer, offset = 0): [<Account>, number] {
  [..]
}

export function serialize(instance: <Account>Args, byteSize?: number): [Buffer, number]
  [..]
}

Then provide them as serializers to Solita or via the solita config:

module.exports = {
  idlGenerator: 'shank',
  [ .. ]
  serializers: {
    Metadata: './src/custom/metadata-deserializer.ts',
  },
};

Hooking into IDL Creation

It is possible to modify the IDL generated by anchor or shank before it is passed to the solita code generator. Just provide an idlHook of the type (idl: Idl) => Idl via the solita config.

This hook takes the current idl as an input and returns the modified version. It is ok to modify the idl parameter in place if that is more convenient.

Please refer to the definition of the Idl type for more details.

Example:

module.exports = {
  idlGenerator: 'anchor',
  [ .. ]
  idlHook: (idl) => {
    return { ...idl, hola: 'mundo' }
  }
};

Advanced Shank + Solita Example

If you need more control you can also add a script. However you're on your own to ensure that the globally installed shank binary matches the version of its library you're using.

  • globally install shank via cargo install shank-cli
  • add a script similar to the below to your SDK package and
const path = require('path');
const { Solita } = require('@metaplex-foundation/solita');
const {
  rustbinMatch,
  confirmAutoMessageConsole,
} = require('@metaplex-foundation/rustbin')
const { spawn } = require('child_process');

const programDir = path.join(__dirname, '..', '..', 'program');
const cargoToml = path.join(programDir, 'Cargo.toml')
const generatedIdlDir = path.join(__dirname, '..', 'idl');
const generatedSDKDir = path.join(__dirname, '..', 'src', 'generated');
const rootDir = path.join(__dirname, '..', '.crates')

const PROGRAM_NAME = 'mpl_token_metadata';
const rustbinConfig = {
  rootDir,
  binaryName: 'shank',
  binaryCrateName: 'shank-cli',
  libName: 'shank',
  dryRun: false,
  cargoToml,
}

async function main() {
  const { fullPathToBinary: shankExecutable } = await rustbinMatch(
    rustbinConfig,
    confirmAutoMessageConsole
  )
  const shank = spawn(shankExecutable, ['idl', '--out-dir', generatedIdlDir, '--crate-root', programDir])
    .on('error', (err) => {
      console.error(err);
      if (err.code === 'ENOENT') {
        console.error(
          'Ensure that `shank` is installed and in your path, see:\n  https://github.com/metaplex-foundation/shank\n',
        );
      }
      process.exit(1);
    })
    .on('exit', () => {
      generateTypeScriptSDK();
    });

  shank.stdout.on('data', (buf) => console.log(buf.toString('utf8')));
  shank.stderr.on('data', (buf) => console.error(buf.toString('utf8')));
}

async function generateTypeScriptSDK() {
  console.error('Generating TypeScript SDK to %s', generatedSDKDir);
  const generatedIdlPath = path.join(generatedIdlDir, `${PROGRAM_NAME}.json`);

  const idl = require(generatedIdlPath);
  const gen = new Solita(idl, { formatCode: true });
  await gen.renderAndWriteTo(generatedSDKDir);

  console.error('Success!');

  process.exit(0);
}

main().catch((err) => {
  console.error(err)
  process.exit(1)
})

Advanced Anchor + Solita Example

If you need more control you can also add a script. However you're on your own to ensure that the globally installed anchor binary matches the version of its library you're using.

  • globally install anchor
  • add a script similar to the below to your SDK package
const path = require('path');
const {
  rustbinMatch,
  confirmAutoMessageConsole,
} = require('@metaplex-foundation/rustbin')
const { spawn } = require('child_process');
const { Solita } = require('@metaplex-foundation/solita');
const { writeFile } = require('fs/promises');

const PROGRAM_NAME = 'candy_machine';
const PROGRAM_ID = 'cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ';

const programDir = path.join(__dirname, '..', '..', 'program');
const cargoToml = path.join(programDir, 'Cargo.toml')
const generatedIdlDir = path.join(__dirname, '..', 'idl');
const generatedSDKDir = path.join(__dirname, '..', 'src', 'generated');
const rootDir = path.join(__dirname, '..', '.crates')

async function main() {
  const { fullPathToBinary: anchorExecutable } = await rustbinMatch(
    rustbinConfig,
    confirmAutoMessageConsole
  )
  const anchor = spawn(anchorExecutable, ['build', '--idl', generatedIdlDir], { cwd: programDir })
    .on('error', (err) => {
      console.error(err);
      // @ts-ignore this err does have a code
      if (err.code === 'ENOENT') {
        console.error(
          'Ensure that `anchor` is installed and in your path, see:\n  https://project-serum.github.io/anchor/getting-started/installation.html#install-anchor\n',
        );
      }
      process.exit(1);
    })
    .on('exit', () => {
      console.log('IDL written to: %s', path.join(generatedIdlDir, `${PROGRAM_NAME}.json`));
      generateTypeScriptSDK();
    });

  anchor.stdout.on('data', (buf) => console.log(buf.toString('utf8')));
  anchor.stderr.on('data', (buf) => console.error(buf.toString('utf8')));
}

async function generateTypeScriptSDK() {
  console.error('Generating TypeScript SDK to %s', generatedSDKDir);
  const generatedIdlPath = path.join(generatedIdlDir, `${PROGRAM_NAME}.json`);

  const idl = require(generatedIdlPath);
  if (idl.metadata?.address == null) {
    idl.metadata = { ...idl.metadata, address: PROGRAM_ID };
    await writeFile(generatedIdlPath, JSON.stringify(idl, null, 2));
  }
  const gen = new Solita(idl, { formatCode: true });
  await gen.renderAndWriteTo(generatedSDKDir);

  console.error('Success!');

  process.exit(0);
}

main().catch((err) => {
  console.error(err)
  process.exit(1)
})

Solita in the Wild

Find more solita, shank and anchor examples inside the metaplex-program-library.

LICENSE

Apache-2.0

More Repositories

1

metaplex

A directory of what the Metaplex Foundation works on!
3,307
star
2

metaplex-program-library

Smart contracts maintained by the Metaplex team
Rust
579
star
3

js

A JavaScript SDK for interacting with Metaplex's programs
TypeScript
307
star
4

sugar

Candy Machine Rust CLI.
Rust
185
star
5

Solana.Swift

This is a open source library on pure swift for Solana protocol.
Swift
158
star
6

umi

A Solana Framework for JS Clients.
TypeScript
147
star
7

js-deprecated

Deprecated Metaplex JavaScript SDK
TypeScript
127
star
8

python-api

Python
123
star
9

kinobi

Generate powerful clients for your Solana programs.
TypeScript
103
star
10

candy-machine-ui

Reference minting UI implementation for the Metaplex Candy Machine Program
TypeScript
70
star
11

amman

A modern mandatory toolbelt to help test solana SDK libraries and apps on a locally running validator.
TypeScript
67
star
12

js-examples

Examples and Starter Kits using the new JS SDK
JavaScript
67
star
13

SolanaKT

This is a open source library on kotlin for Solana protocol.
Kotlin
67
star
14

digital-asset-rpc-infrastructure

Reference implementation for Metaplex Digital Asset Standard API
Rust
66
star
15

mpl-bubblegum

Create and manage Metaplex compressed NFTs
Rust
65
star
16

shank

Extracts IDL from Solana Rust contracts
Rust
61
star
17

docs

docs.metaplex.com source code
JavaScript
43
star
18

digital-asset-validator-plugin

The NFT Geyser plugin that powers metaplex APIs
Rust
33
star
19

blockbuster

Canonical Program Parsing from Geyser Plugins
Rust
27
star
20

gumdrop

Gumdrop!
TypeScript
27
star
21

beet

Borsh compatible De/Serializer
TypeScript
26
star
22

mpl-token-auth-rules

A program that provides the ability to create and execute rules to restrict common token operations such as transferring and selling.
HTML
24
star
23

metaplex-ios

Metaplex Mobile IOS SDK
Swift
23
star
24

mpl-candy-guard

Access control logic for Metaplex Candy Machine.
21
star
25

get-collection

Rust and TypeScript example code for finding all members from a collection id.
Rust
21
star
26

metaplex-android

Metaplex Mobile Android SDK
Kotlin
18
star
27

compression-read-api-js-examples

TypeScript
16
star
28

aura

Rust
16
star
29

mip

14
star
30

mpl-candy-machine

Mint your NFT collection on Solana
TypeScript
12
star
31

mpl-toolbox

Essential programs and clients to build on top of.
TypeScript
10
star
32

solana-kmp

Kotlin
9
star
33

lut

A simple CLI for creating and managing Solana Lookup Tables.
Rust
8
star
34

mplex

Metaplex CLI to interact with the Metaplex SDK
TypeScript
7
star
35

arweave-cost

Calculates the cost of uploading files to Arweave
TypeScript
7
star
36

js-react-native

Java
6
star
37

mpl-trifle

The core composability contract for Metaplex Fusion
TypeScript
5
star
38

amman-explorer

Amman Solana Explorer
TypeScript
5
star
39

api-specifications

Public Documentation for our Written Specifications that have multi party implementations
5
star
40

token-entangler-ui

A UI for the token entangler program
TypeScript
5
star
41

mpl-token-metadata

Client library for the Token Metadata program
TypeScript
4
star
42

goose

A CLI for interacting with the mpl-migration-validator program.
Rust
4
star
43

themis

A CLI to allow our automated workflows to make proposals to spl-governance programs.
Rust
4
star
44

deprecated-storefront

The Metaplex Storefront frontend that is no longer maintained by the Metaplex Foundation
TypeScript
3
star
45

solana-project-template

A template for vanilla Solana programs and their clients
TypeScript
3
star
46

cusper

Resolves custom program errors from solana logs or error codes.
TypeScript
3
star
47

solita-swift

Sol ana I DL t o A PI generator.
Swift
3
star
48

digital-asset-protocol

Rust
3
star
49

florida

Where programs go to retire.
Rust
3
star
50

actions

A set of useful GitHub actions for Solana devs
3
star
51

deprecated-clis

A collection of JS CLIs that are no longer maintained by the Metaplex Foundation
TypeScript
3
star
52

fusion-dressing-room

Fusion user-facing UI forked from Solana dApp Scaffold
TypeScript
3
star
53

metaplex-incubating-programs

Programs that have not met the maturity, security and stability requirements live here, free of charge with community stewards
Rust
3
star
54

Metaplex-Deployer

2
star
55

shank-js

Generate IDL files via Anchor or Shank.
TypeScript
2
star
56

mpl-hydra

Client library for the Hydra program
TypeScript
2
star
57

umi-hotline

2
star
58

beet-swift

Swift
2
star
59

larry-discord-bot

The Larry Discord bots we use in our Discord server!
TypeScript
2
star
60

metaplex-swift-program-library

Generated Code for metaplex-ios
Swift
2
star
61

das-api-testing

Rust
2
star
62

listing-rewards-auctioneer

1
star
63

firewall

Solana Account Firewall
Rust
1
star
64

rooster

Three crows, and you're out. But there is always grace.
Rust
1
star
65

auctioneer-template

Template program for users to build their own Auctioneer
Rust
1
star
66

rustbin

Synchronizes a Rust binary version with the related Rust crate
TypeScript
1
star
67

mpl-migration-validator

Asset migration validator program, to be used in conjuction with Token Metadata to enable asset class migrations.
Rust
1
star
68

check-collections

Rust
1
star
69

mpl-core

Rust
1
star
70

fusion-ui

The Proof-of-Concept UI interfaces for Composable NFTs
TypeScript
1
star