npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@primitivefi/rmm-ethers

v1.2.0-rc.1

Published

∇ Primitive RMM Protocol ethers-based implementation.

Downloads

10

Readme

🍄 rmm-ethers

version npm license stars

Easily connect and transact with RMM protocol.

🧩 Features

  • 🌲 Deploy RMM protocol
  • ⚡️ Easily connect to an RMM deployment
  • 🌊 Create RMM pools
  • ☄️ Allocate or remove liquidity
  • 🎁 Transfer positions
  • 🔭 Read protocol data

📦 Installation

This software is in Alpha. Use at your own risk. Only use the latest version.

Installing locally:

# Clone the repository
git clone https://github.com/primitivefinance/rmm-ethers.git

# Install dependencies
yarn install

Installing as a package:

# Using yarn
yarn add @primitivefi/rmm-ethers

# Or using npm
npm i @primitivefi/rmm-ethers

Use it by connecting with a signer or provider:

// Import the EthersRmm class
import { EthersRmm } from '@primitivefi/rmm-ethers'

// Use the class by connecting to a deployment
await EthersRmm.connect(signerOrProvider)

✏️ Usage as a Package

This package is designed to extend the rmm-sdk package. The SDK has the entity models and interfaces that are used by rmm-ethers to send transactions.

🪝 As a react hook:

Here is an example of a React hook that makes use of web3-react and SWR:

import useSWR, { SWRResponse } from 'swr'
import { useWeb3React } from 'web3-react'
import { Signer } from '@ethersproject/abstract-signer'
import { EthersRmm } from '@primitivefi/rmm-ethers'

function getEthersRmm(signerOrProvider: Signer | Provider): () => Promise<EthersRmm> {
  return async () => await EthersRmm.connect(signerOrProvider)
}

/**
 * Connects to EthersRmm deployment from the connected provider or signer.
 */
export function useRmmProtocol(suspense = false): SWRResponse<EthersRmm, Error> {
  const { library: signerOrProvider, chainId } = useWeb3React()
  const shouldFetch = !!signerOrProvider && typeof chainId !== 'undefined'
  const result = useSWR(
    shouldFetch ? [signerOrProvider, 'ethers-rmm', chainId] : null,
    getEthersRmm(signerOrProvider?.getSigner() as Signer),
    {
      dedupingInterval: 60 * 1000,
      refreshInterval: 60 * 1000,
      suspense,
    },
  )

  return result
}

🌊 Fetch a pool

import { Pool } from '@primitivefi/rmm-sdk'
import { EthersRmm, Position } from '@primitivefi/rmm-ethers'

async function getPool(poolId: string): Promise<Pool> {
  return rmm.getPool(poolId).then(data => data)
}

⚱️ Fetching pool liquidity positions

import { Pool } from '@primitivefi/rmm-sdk'
import { EthersRmm, Position } from '@primitivefi/rmm-ethers'

async function getPoolPosition(pool: Pool, account: string): Promise<Position> {
  return rmm.getPosition(pool, account).then(data => data)
}

Adjusting Positions

When allocating or removing liquidity, the arguments must match the respective interfaces, which live in the rmm-sdk:

/** Flag to use a native currency in a transaction.  */
export interface NativeOptions {
  useNative?: NativeCurrency
}

/** Recipient address of any tokens which are output from transactions. */
export interface RecipientOptions {
  recipient: string
}

/** Timestamp which will revert the transaction if not yet mined. */
export interface Deadline {
  deadline?: BigNumber
}

/** Permit details on either risky or stable tokens. */
export interface PermitTokens {
  /** If defined, risky token can be permitted, saving the user an approve tx. */
  permitRisky?: PermitOptions

  /** If defined, stable token can be permitted, saving the user an approve tx. */
  permitStable?: PermitOptions
}

/** Token amounts to use for depositing or withdrawing into a margin account.  */
export interface MarginOptions extends PermitTokens, RecipientOptions, NativeOptions {
  amountRisky: Wei
  amountStable: Wei
}

/** Token amounts to use for allocating liquidity. */
export interface LiquidityOptions {
  /** Amount of risky tokens to provide as liquidity. */
  delRisky: Wei
  /** Amount of stable tokens to provide as Liquidity. */
  delStable: Wei
  /** Desired liquidity to mint. */
  delLiquidity: Wei
}

/** Provide liquidity argument details. */
export interface AllocateOptions extends PermitTokens, LiquidityOptions, RecipientOptions, NativeOptions, Deadline {
  fromMargin: boolean
  slippageTolerance: Percentage
  createPool?: boolean
}

/** Remove liquidity argument details. */
export interface RemoveOptions extends LiquidityOptions, RecipientOptions, NativeOptions, Deadline {
  additionalRisky: Wei
  additionalStable: Wei
  toMargin: boolean
  slippageTolerance: Percentage
}

🕳️ Allocating liquidity

import { Pool, AllocateOptions } from '@primitivefi/rmm-sdk'
import { EthersRmm, PositionAdjustmentDetails } from '@primitivefi/rmm-ethers'

async function onAllocate(rmm: EthersRmm, pool: Pool, options: AllocateOptions): Promise<PositionAdjustmentDetails> {
  return rmm.allocate({ pool, options }).then(data => data)
}

💎 Removing liquidity

import { Pool, AllocateOptions } from '@primitivefi/rmm-sdk'
import { EthersRmm, PositionAdjustmentDetails } from '@primitivefi/rmm-ethers'

async function onRemove(rmm: EthersRmm, pool: Pool, options: RemoveOptions): Promise<PositionAdjustmentDetails> {
  return rmm.remove({ pool, options }).then(data => data)
}

🧮 Usage locally

Before running any command, make sure to install dependencies:

yarn install

Compile

Compile the smart contracts with Hardhat:

yarn compile

Test

Run the Mocha tests:

yarn test

📃 Deploy RMM

Deploy the protocol to a network:

yarn deploy --network nameOfNetwork

This will call a hardhat task that deploys the RMM protocol contracts from a loaded signer and saves the addresses to /deployments.

Here are the options for the deploy task:

  • --defender (optional): Flag to attempt to use an Open Zeppelin Defender Relay Signer, if it exists in the hardhat.config.ts file.
  • --channel (optional): Directory name in /deployments/ to save the deployment to.
  • --gasPrice (optinal): Price to pay for gas.
  • --testweth (optional): Only for test networks, allows specifying a WETH9 address.

Deploy Primitive Engines - Pair contracts

yarn deploy:engine --network nameOfNetwork

This is a script that runs which requires two of the token addresses. Here is the script, which should be edited to suit the deployment needs:

import hre from 'hardhat'
import { Signer } from '@ethersproject/abstract-signer'
import { DefenderRelaySigner } from 'defender-relay-client/lib/ethers'
import { deployEngine } from '../utils/deployEngine'

type Signers = Signer | DefenderRelaySigner

export async function main() {
  const signer: Signers = await hre.run('useSigner')

  const rmm = await hre.connect(signer)
  const chainId = rmm.connection.chainId
  if (chainId === 1) throw new Error('Do not use this in prod!')

  const risky = '0xc778417E063141139Fce010982780140Aa0cD5Ab' // rinkeby:WETH: FIX
  const stable = '0x522064c1EafFEd8617BE64137f66A71D6C5c9aA3' // rinkeby:USDC: FIX

  await deployEngine(rmm, risky, stable)
}

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

🪞 Deploy RMM Pools Script

Warning: Currently failing for node versions above 14.7.4. Unresolved promises are not handled in the higher node versions, and instead the process is exited with a non-zero error code.

Work in progress: This script is still being improved! Consider it an alpha version.

Deploy pools in the config of the deploy-pools.ts script:

yarn deploy:pools --network nameOfNetwork

Creating RMM pools is a process that requires connecting to the protocol, fetching token metadata, and building the transaction's arguments. This script handles loading tokens from a saved pool deployment, located in /deployments/*/pools.json.

All the logic executed by a hardhat script must exist in the script file. Here is an example:

import hre from 'hardhat'
import { EthersRmm } from 'src/EthersRmm'
import { deployPools } from 'utils/deployPools'
import { poolDeployer } from 'utils/poolDeployer'

export async function main() {
  const signer: Signers = await hre.run('useSigner')
  const from = await signer.getAddress()

  const rmm = await hre.connect(signer)

  const chainId = rmm.connection.chainId

  if (chainId === 1) throw new Error('Do not use this in prod!')

  const deployer = new PoolDeployer(chainId, POOL_DEPLOYMENTS_SAVE, POOL_CONFIG_TO_DEPLOY, rmm)

  await deployPools(deployer)
}

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

📌 Misc. Scripts

Generate documentation locally:

yarn docs

Deploy to a local ganache-cli instance:

yarn deploy:devnet

Delete a local deployment to ganache-cli:

yarn delete-dev-deployments

🛡️ Use with Open Zeppelin Defender Relays

The OZ Defender relayers are a safer way to execute transactions on-chain.

The hardhat.config.ts is extended to include OZ defender relay API key and secret:

defender: {
    [chainIds.rinkeby]: {
      apiKey: RELAY_RINKEBY_API || '',
      apiSecret: RELAY_RINKEBY_SECRET || '',
    },
}

Adding this to the hardhat config will expose the relay signer through the task useSigner.

This task is currently only used in the deployPools.ts script, so pools can be deployed safely from the OZ defender relay.

🖋️ useSigner

If this subtask is run from task run with a --network flag, and the network has an OZ relayer config in the hardhat config file, this task will return the Signer object for the relayer. Else, useSigner will default to the ethers.getSigners(). This subtask can be used in custom scripts so you can choose to use a relayer or a private key stored in .env.

  • --i (optional): Index of the signer to use from ethers.getSigners()

⛑ Contribute

Feel free to suggest changes by opening a pull request, or posting an issue. There is a dedicated dev channel in the Primitive discord.

Credits

Inspired by Liquity Ethers.