ChorusOne/solido

Add a typescript/js SDK for interacting with the Solido program

Opened this issue · 3 comments

ruuda commented

Summary

There are various parties interacting with Solido from javascript. Until now we just had a dump of some useful snippets on https://docs.solana.lido.fi/development/frontend-integration, but we can do much better than this by offering a library.

  • Constructing a deposit instruction manually is a bit tedious but doable, but to construct an unstake instruction is a bit involved, and it relies on things that I would consider implementation details.
  • If integrations write their own logic for interacting with the Solido program, it also makes it more difficult for us to change things in the future without breaking these use cases.
  • It will be smoother for new integrations if they can use a library, instead of having to copy some snippets from the docs site.

Details

We should offer the following functions:

  • Get the current Total Value Locked (amount in stake accounts + reserve) in SOL
  • Get the current stSOL supply.
  • Get the epoch exchange rate (from the instance, it is not just TVL / stSOL supply).
  • Construct a deposit instruction.
  • Construct a withdraw instruction.

Probably we should parametrize those functions over the addresses, and then also offer one constant that contains the official mainnet addresses.

An attempt at defining this, but I know nothing about Typescript so feel free to correct me here:

// TODO: Is it better to use an interface or class for this?
interface Addresses {
    solidoProgramId: PublicKey;
    solidoInstanceId: PublicKey;
    stSolMintAddress: PublicKey;
}

const MAINNET_ADDRESSES: Addresses = {
    solidoProgramId: web3.PublicKey("CrX7kMhLC3cSsXJdT7JDgqrRVWGnUpX3gfEfxxU2NVLi"),
    solidoInstanceId: web3.PublicKey("49Yi1TKkNyYjPAFdR9LBvoHcUjuPX4Df5T5yv39w2XTn"),
    stSolMintAddress: web3.PublicKey("7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj"),
};

interface Lamports { lamports: BigNumber; }
interface StLamports { stLamports: BigNumber; }

interface ExchangeRate {
    solBalance: Lamports;
    stSolSupply: StLamports;
}

interface Snapshot { /* Should hold the data for all relevant accounts. */ }

// Reads the Solido instance and stSOL mint through getMultipleAccounts.
function getSnapshot(connection: Connection, addrs: Addresses): Snapshot { /* ... */ }

// Or maybe these should be methods on `Snapshot`, that would work as well.
function getTotalValueLocked(snapshot: Snapshot): Lamports { /* ... */ }
function getStSolSupply(snapshot: Snapshot): StLamports { /* ... */ }
function getExchangeRate(snapshot: Snapshot): ExchangeRate { /* ... */ }

function deposit(senderSol: PublicKey, recipientStSol, amount: Lamports): TransactionInstruction { /* ... */ }
// Maybe we can also have an function to build the instruction to initialize the associated token account.

// Note: Withdraw initializes the recipient stake account; it should be a new fresh address.
// Would throw an exception if the amount is too low (can happen due to the stake account rent exemption requirement)
// or too high (can happen due to balancing requirements).
function withdraw(
    snapshot: Snapshot,
    senderStSol: PublicKey,
    recipientWithdrawAuthority: PublicKey,
    recipientStakeAccount: PublicKey,
    amount: StLamports,
): TransactionInstruction { /* ... */ }

Open questions

We can put the thing in this repository. @hritique, I am not very familiar with the js ecosystem ... should we also upload a package to NPM or something?

Also, my impression is that Typescript is taking over, and a Typescript library can be used from js after compilation, right? So probably it is most useful to offer it in Typescript so users who are also using it get maximum type safety, but users who are using legacy js can still use it? I see solana-web3 is also written in Typescript, so that would fit in nicely.

ruuda commented

Also, the code in this repository is currently licensed under the GPLv3, but for a library that is not ideal, we should go with something permissive for this part.

We already have some of these features pulled together for Steakwallet.

What we could do is separate it out into an MIT based library and someone with more knowhow fills in the rest of the functions. The withdraw functionality is a little complicated, for example, which is what we're blocked on right now

ruuda commented

A work in progress is in #478.