0.2.2 • Published 1 year ago

@hedgefarm/alpha3-sdk v0.2.2

Weekly downloads
-
License
-
Repository
-
Last release
1 year ago

Project overview

Automated market-making Strategies.

The purpose of this project is to allocate as efficiently as possible two assets in a Concentrated Liquidity Market Maker pool to generate a real yield. Indeed, the narrower the price range, the greater the fees but also the impermanent loss. Thus managing Concentrated Liquidity Market Maker position can be tricky, you can still lose money even if the APR is big.

Our quantitative model tracks price and volatility to find the best bounds of our position to maximize returns while minimizing impermanent loss, so that you don't have to constantly monitor the market.

Rebalancing a Concentrated Liquidity Market Maker position can be really costly because impermanent loss becomes realized loss. If you add swap fees/price impact on top of that it can be really hard to be profitable, this is why we use Jupiter to rebalance our position.

Jupiter being a web2 solution, Orca pools can be used in case of web2 unavailability .

This project is build on top of Orca-Whirlpool on Solana.

flowchart LR
  subgraph Alpha4
  subgraph Alpha4Vault
    direction RL
    acc1([TokenAccountA])
    acc2([TokenAccountB])
    acc3([LpMint])
    acc4([PositionTokenAccount])
  end
  end
  subgraph User
      fn1(deposit)
      fn2(withdraw)
  end
  subgraph Admin
      direction RL
      fn3(initializeVault)
      fn4(setVaultParameters)
      fn5(pause/unPause)
      fn6(panic)
  end
  subgraph PositionChanger/Admin/Bot
      fn7(changePosition)
      fn8(rebalance)
      fn9(addLiquidity)
  end
  subgraph Whirlpool
      acc5([Position])
  end
  User -.-> Alpha4Vault
  Admin -.-> Alpha4Vault
  PositionChanger/Admin/Bot -.-> Alpha4Vault
  Alpha4Vault --rebalance using--> Orca
  Alpha4Vault --rebalance using--> Jupiter
  Alpha4Vault --manage liquidity--> Whirlpool

  api((Jupiter v4 API))--swap quote--> fn8
  style api fill:#b2ff66,stroke:#333,stroke-width:3px

  style User fill:#66ff66,stroke:#333,stroke-width:3px
  style Admin fill:#ff0,stroke:#333,stroke-width:3px
  style PositionChanger/Admin/Bot fill:#3399ff,stroke:#333,stroke-width:3px

  classDef vault fill:#b266ff,stroke:#333,stroke-width:3px
  Alpha4Vault:::vault

  classDef fn stroke:#333,stroke-width:2px
  fn1:::fn
  fn2:::fn
  fn3:::fn
  fn4:::fn
  fn5:::fn
  fn6:::fn
  fn7:::fn
  fn8:::fn
  fn9:::fn
  classDef acc stroke:#333,stroke-width:2px
  acc1:::acc
  acc2:::acc
  acc3:::acc
  acc4:::acc
  acc5:::acc

  classDef program fill:#ff6666,stroke:#333,stroke-width:3px
  Alpha4:::program
  Whirlpool:::program
  Jupiter:::program
  Orca:::program

Noticeable Accounts :

  • TokenAccountA : token account of token A to handle deposit/withdraw and unused liquidity
  • TokenAccountB : token account of token B to handle deposit/withdraw and unused liquidity
  • LpMint : mint to represent the shares of a vault.
  • PositionTokenAccount : account which owns the current opened position on Whirlpool

TokenAccountA, TokenAccountB, LpMint and PositionTokenAccount are owned by an Alpha4Vault. Thus their behavior is strictly defined by the program, even admin can't have possession of it.

See doc on lib.rs for more explanation.

Setup

Install Rust, Solana, (Yarn or NPM) and Anchor, check here

yarn install or npm install

Build smart contract: anchor build

At the build time, this error appears, we ignore it.

Error: Function _ZN10whirlpools81_$LT$impl$u20$core..default..Default$u20$for$u20$whirlpools..state..TickArray$GT$7default17h09c7cd609a105921E Stack offset of 9944 exceeded max offset of 4096 by 5848 bytes, please minimize large stack variables

Make sure the sdk is correctly building by running npm run build

Architecture

This smart contract is build in bpf - default with our anchor version at the moment. (The other architecture is sbf).

To be sure that anchor is building at the right place, you can run: anchor build --arch bpf.

Run test

The test are run in local net. Since the test uses Orca, Whirlpool and Jupiter, we need to download their associated program. We place them in programs-to-load at the root of the project.

To do so we need to dump the program on-chain : solana program dump -u https://api.mainnet-beta.solana.com <ACCOUNT_ADDRESS> <OUTPUT_FILEPATH>

  • orca: 9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP, file programs-to-load/orca.so
  • whirlpool : whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc, file programs-to-load/whirlpool.so
  • jupiter : JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB, file programs-to-load/jupiter.so

The address that own those program in the Anchor.toml doc is here

Run on localnet

  • Unit tests in rust: cargo test
  • Unit tests in Javascript: anchor run sdk-test
  • Smart contract integration tests: anchor test --detach. Then you can browse the transactions here

Run on devnet

We really do not encourage to run the tests on devnet.
You will encounter rate limitation for getting enough dev SOl on your wallet, test will be slower to run, etc...

  • Be sure that the contract is deployed in devnet
  • Uncomment the devnet part in Anchor.toml
  • Comment the localnet part in Anchor.toml
  • Export env vars :
export ANCHOR_PROVIDER_URL=https://api.devnet.solana.com
export ANCHOR_WALLET=path_to_your_json_wallet
  • Don't forget to use the Alpha4Config corresponding. Look for alpha4TestConfig
  • Use a custom keypair for anchorFaucetKeypair.
  • Be sure to have enough money in anchorFaucetKeypair. We encourage you to use this repo to get enough token and not be limited by solana airdrop
  • Smart contract integration tests: anchor test --skip-deploy

Push new version on Npm

Follow the installation process of np and run at the root of the project:

npm login
npm run build
np

Update the version and changes in changelog

Formatting

Rust: cargo fmt Typescript : npx prettier --write .

Expand code generated by anchor

Used for create_idl

cargo install cargo-expand
anchor expand

The code will be generated in .anchor/expanded-macros/[your_program]

Testing contract in mainnet / testnet / devnet

Interact with testing contract

See script folder. You will need to update pathToKeypair and the alpha4Config.

Airdrop some SOL to be able to deploy the program on devnet (to do several time): solana airdrop 2 deploy/deployment-devnet-keypair.json --url devnet

You can create your own token and whirlpool see setupTestEnvironment

Deploy contract

First make sure the declare_id of the program is the same as solana address -k target/deploy/alpha4_contracts_dev-keypair.json.

For testing in mainnet, we can use:

ts-node scripts/deploy.ts -u mainnet-beta -k 'path/to/payer' -p target/deploy/alpha4_contracts_dev.so -i target/deploy/alpha4_contracts_dev-keypair.json

Sometimes, the transaction can be dropped, so you'll get this error : SendTransactionError: failed to send transaction: Transaction simulation failed: Blockhash not found, the only solution is to retry. If the deploy fails, close the temporary buffer account and retry.

Publish IDL

  • use our function create_idl to create an idl account (This allocates an account of exactly MAX_PERMITTED_DATA_INCREASE bytes for the idl). Needs to be called by the admin
  • anchor idl upgrade --provider.cluster mainnet --provider.wallet [admin] -f target/idl/alpha4_contracts_dev.json [program_id] For publishing with the multisig will probably require the use of: anchor idl write-buffer ... and anchor idl set-buffer ...

Orca whirlpool notes

Whirlpools is concentrated liquidity automated market maker (CLAMM) program build on solana. It allows adding liquidity in specified range to maximize fees (like UniV3 pools).

A Whirlpool is a concentrated liquidity pool between a token pair (A & B). (docs link)

GH link to on-chain instructions that we can call on Whirlpools

Multisig

Squads seems to be a really nice solution

Pros :

  • code open-source link
  • program not upgradable link
  • code audited
  • no fees
  • really smooth UI
  • you can directly interact though the UI with programs that have a on-chain deployed IDL.

Cons :

  • transaction cost higher because of rent
  • transaction is stored on chain before execution so it can be more easily front run

To upgrade contract with multisig, first deploy the buffer update:

solana program write-buffer --url mainnet-beta --buffer-authority <multisig-address> <path-to-program-updated.so>

Then create an upgrade transaction proposal on squads in the develop section and sign it.

Contract monitoring/Alerting

Not done for the at the moment, you can find here some possible solution

1) Substreams

Check here and the current work here

Pros :

  • mapping done in Rust => really easy to extract complex schema
  • can access past data

Cons :

  • cannot access account's data
  • you have to host the data extraction and the storage

2) Event publisher/listener

Anchor provides a way to publish event from smart-contract and to listen to it, check here and here

Pros :

  • easy to use
  • you extract data later in logs by parsing block
  • react to live event

Cons :

  • you cannot access to past data
  • event are stored on chain but you may need to handle data storage for fast and easy access

3) Indexer

Solana FM and Helius provides some solutions for data monitoring

Pros :

  • hosted
  • "plug and play"

Cons :

  • not powerful at the moment, can't extract complex data

Useful docs

Whirlpools source code here

Orca documentation here

Orca Developer Portal here

Airdrop tool here

Orca Sandbox repo here

Jupiter CPI repo here