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

@relicprotocol/client

v0.2.2

Published

Client SDK for interacting with Relic Protocol

Downloads

23

Readme

Relic Client SDK

The client SDK is designed to simplify fetching proofs from the Relic Prover and generating transaction data to be submitted on-chain for verification.

Relic Architecture Overview

Usage

Initializing RelicClient requires passing an ethers Provider. Providers can be created with an RPC url or by connecting to Metamask or another wallet extension.

import { AccountNotFound, RelicClient, utils, InfoType } from '@relicprotocol/client'
import { ethers } from 'ethers'

async function main() {
  // Note: you could also get the provider from a browser wallet extension
  const provider = new ethers.providers.JsonRpcProvider('[RPC URL here]')
  const signer = await provider.getSigner()

  const relic = await RelicClient.fromProvider(provider)

  // prove an account's birth certificate
  const account = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' // vitalik.eth
  const bcTx = await relic.birthCertificateProver.prove({ account })
  console.log(await provider.estimateGas(bcTx))

  // use the transaction data...
  // to send the proof transaction as is:
  // let tx = await signer.sendTransaction(bcTx)
  // await tx.wait()

  // prove an account's code hash
  // note: other account data fields can be proven by changing the |info| param
  const aiTx = await relic.accountInfoProver.prove(
      { block, account, info: InfoType.CodeHash }
  )
  // use the transaction data...
  console.log(await provider.estimateGas(aiTx)

  // prove a storage slot's value, in this case WETH.balanceOf(account)
  const blockNum = 15000000
  const wethAddr = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' // WETH
  const slot = utils.mapElemSlot(3, account) // calculate balanceOf(account) slot

  // you can optionally specify the expected slot value, to ensure the slot is correct
  // we'll compute this by calling balanceOf(account) at the target block
  const contract = new ethers.Contract(
    wethAddr,
    ['function balanceOf(address) external view returns (uint256)'],
    provider
  )
  const expected = await contract.balanceOf(account, { blockTag: blockNum })

  // expected is optional parameter
  const ssTx = await relic.storageSlotProver.prove({
    block: blockNum,
    account: wethAddr,
    slot,
    expected,
  })

  // use the transaction data...
  console.log(await provider.estimateGas(ssTx))

  // You can also prove multiple storage slots in one call to save gas
  const ZERO_ADDR = '0x' + '0'.repeat(40)
  const slot2 = utils.mapElemSlot(3, ZERO_ADDR) // calculate balanceOf(0x000..00) slot
  const expected2 = await contract.balanceOf(ZERO_ADDR, { blockTag: blockNum })

  // prove two storage slots from the same account simultaneously
  const mssTx = await relic.multiStorageSlotProver.prove({
    block: blockNum,
    account: wethAddr,
    slots: [slot, slot2],
    expected: [expected, expected2],
  })

  // use the transaction data...
  console.log(await provider.estimateGas(mssTx))

  // prove the storage root an account in a particular block,
  // potentially making slot proofs in that block much cheaper
  const asTx = await relic.accountStorageProver.prove({
    block: 15000000,
    account: wethAddr,
  })
  console.log(await provider.estimateGas(asTx))

  // once the above transaction is confirmed, you can use cheap cached storage
  // slot proofs for that (account, block)
  const cssTx = await relic.cachedStorageSlotProver.prove({
    block: blockNum,
    account: wethAddr,
    slot,
    expected,
  })
  // use the transaction data...
  console.log(await provider.estimateGas(cssTx))

  // Now let's prove some ephemeral facts; a block header proof and a log proof
  // NOTE: you probably don't want to prove these facts without using proveEphemeral,
  // because storing these large facts on-chain costs a lot of gas

  // Your contract which implements IRelicReceiver
  // Consider using the RelicReceiver base contract in the solidity SDK
  const receiver = '0x...'

  // prove a historical block header is valid
  const bhTx = await relic.blockHeaderProver.proveEphemeral(
    {
      initiator: await signer.getAddress(),
      receiver,
      gasLimit: 50000, // 50000 gas is enough for our receiver callback, be sure to check yours!
    },
    { block: 15000000 }
  )
  console.log(await signer.estimateGas(bhTx))

  // get BAYC mint events
  // NOTE: this may be very slow if your RPC provider doesn't index logs well
  const logs = await provider.getLogs({
    address: '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D', // BAYC contract
    topics: [
      '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', // Transfer event
      '0x0000000000000000000000000000000000000000000000000000000000000000', // from == address(0)
    ],
    fromBlock: 0,
  })

  // prove the first BAYC mint log
  const logTx = await relic.logProver.proveEphemeral(
    {
      initiator: await signer.getAddress(),
      receiver,
      gasLimit: 50000,
    },
    logs[0]
  )

  // use the transaction data...
  console.log(await signer.estimateGas(logTx))

  // prove the first withdrawal
  const withdrawalTx = await relic.withdrawalProver.prove({
    block: 17034871,
    idx: 0,
  })
  // use the transaction data...
  console.log(await signer.estimateGas(withdrawalTx))

  // prove a transaction was included
  const receipt = await provider.getTransactionReceipt(logs[0].transactionHash)
  const txTx = await relic.transactionProver.prove(receipt)

  // use the transaction data...
  console.log(await signer.estimateGas(txTx))

  // prove a beacon chain withdrawal occured
  const withdrawalTx = await relic.withdrawalProver.prove(
      { block: 17034871, idx: 0 } // first withdrawal in the first shapella block
  )
  // use the transaction data...
  console.log(await signer.estimateGas(withdrawalTx))


  // demonstrate error handling
  try {
    const randomAddr = ethers.utils.hexlify(ethers.utils.randomBytes(20))
    await relic.birthCertificateProver.prove({ account: randomAddr })
  } catch (error: any) {
    if (!(error instanceof AccountNotFound)) throw error
    // handle account not found
  }
}

main()