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

@weiroll/weiroll.js

v0.3.0

Published

The weiroll planner in JS

Downloads

505

Readme

weiroll.js

CIsize

weiroll.js is a planner for the operation-chaining/scripting language weiroll.

It provides an easy-to-use API for generating weiroll programs that can then be passed to any compatible implementation.

Installation

npm install --save @weiroll/weiroll.js

Usage

Wrapping contracts

Weiroll programs consist of a sequence of calls to functions in external contracts. These calls can either be delegate calls to dedicated library contracts, or standard/static calls to external contracts. Before you can start creating a weiroll program, you will need to create interfaces for at least one contract you intend to use.

The easiest way to do this is by wrapping ethers.js contract instances:

const ethersContract = new ethers.Contract(address, abi);
const contract = weiroll.Contract.newLibrary(ethersContract);

This will produce a contract object that generates delegate calls to the contract in ethersContract.

To create regular or static calls to an external contract, use newContract:

const ethersContract = new ethers.Contract(address, abi);
// Makes calls using CALL
const contract = weiroll.Contract.newContract(ethersContract);
// Makes calls using STATICCALL
const contract = weiroll.Contract.newContract(ethersContract, CommandFlags.STATICCALL);

You can repeat this for each contract you wish to use. A weiroll Contract object can be reused across as many planner instances as you wish; there is no need to construct them again for each new program.

Planning programs

First, instantiate a planner:

const planner = new weiroll.Planner();

Next, add one or more commands to execute:

const ret = planner.add(contract.func(a, b));

Return values from one invocation can be used in another one:

planner.add(contract.func2(ret));

Remember to wrap each call to a contract in planner.add. Attempting to pass the result of one contract function directly to another will not work - each one needs to be added to the planner!

For calls to external contracts, you can also pass a value in ether to send:

planner.add(contract.func(a, b).withValue(c));

withValue takes the same argument types as contract functions, so you can pass the return value of another function, or a literal value. You cannot combine withValue with delegate calls (eg, calls to a library created with Contract.newLibrary) or static calls.

Weiroll only supports functions that return a single value by default. If your function returns multiple values, though, you can instruct weiroll to wrap it in a bytes, which subsequent commands can decode and work with:

const ret = planner.add(contract.func(a, b).rawValue());

Once you are done planning operations, generate the program:

const { commands, state } = planner.plan();

Subplans

In some cases it may be useful to be able to instantiate nested instances of the weiroll VM - for example, when using flash loans, or other systems that function by making a callback to your code. The weiroll planner supports this via 'subplans'.

To make a subplan, construct the operations that should take place inside the nested instance normally, then pass the planner object to a contract function that executes the subplan, and pass that to the outer planner's .addSubplan() function instead of .add().

For example, suppose you want to call a nested instance to do some math:

const subplanner = new Planner();
const sum = subplanner.add(Math.add(1, 2));

const planner = new Planner();
planner.addSubplan(Weiroll.execute(subplanner, subplanner.state));
planner.add(Events.logUint(sum));

const {commands, state} = planner.plan();

Subplans

In some cases it may be useful to be able to instantiate nested instances of the weiroll VM - for example, when using flash loans, or other systems that function by making a callback to your code. The weiroll planner supports this via 'subplans'.

To make a subplan, construct the operations that should take place inside the nested instance normally, then pass the planner object to a contract function that executes the subplan, and pass that to the outer planner's .addSubplan() function instead of .add().

For example, suppose you want to call a nested instance to do some math:

const subplanner = new Planner();
const sum = subplanner.add(Math.add(1, 2));

const planner = new Planner();
planner.addSubplan(Weiroll.execute(subplanner, subplanner.state));
planner.add(Events.logUint(sum));

const {commands, state} = planner.plan();

Subplan functions must specify which argument receives the current state using the special variable Planner.state, and must take exactly one subplanner and one state argument. Subplan functions must either return an updated state or nothing.

If a subplan returns updated state, return values created in a subplanner, such as sum above, can be referenced in the outer scope, and even in other subplans, as long as they are referenced after the command that produces them. Subplans that do not return updated state are read-only, and return values defined inside them cannot be referenced outside them.