Run is a platform to build apps and tokens on Bitcoin. Developers create applications using interactive objects, called jigs. Jigs allow you to build almost anything you can dream up: tokens, contracts, artwork, elections, games, digital pets, and more — all run on Bitcoin.

Run supports full object-oriented programming and arbitrary code today. It is secure and performant for real applications. These docs will help you get started!

Getting Started


Load both bsv and run in the browser

<script src=""></script>
<script src=""></script>

Load run in Node.js

const Run = require('run-sdk')

If you're new to Run, let the tutorial series guide your journey to get acquainted. You can write code without installing anything. The web browser Console will be your playground.

The details written here in the Docs have example code in the sidebar on the right-hand side. Anything you read in paragraphs, you can preview in-action over there. ⇥

Run works everywhere including all major browsers, on desktop and mobile, as well as Node.js 10+ on servers. The Run SDK is written in JavaScript ES6 and uses the bsv library to build and sign transactions. To get started:

And that's it. All your code and jigs will be saved on-chain and Run will use public APIs to interact with the Bitcoin network. You don't need to deploy any servers to use Run. All the logic works client-side.


const run = new Run({ network: 'mock' })

A Run instance manages your communication with the Bitcoin network. The default network is main (Mainnet), but for development and testing, we recommend mock. Mock is an in-memory simulation blockchain that does not require funds to use. We like to call it the mockchain. For more configuration options, see API Reference: Run.

Creating Jigs

class SimpleStore extends Jig {
  set(value) {
    this.value = value

const jig = new SimpleStore()

jig.set('Satoshi Nakamoto')

await jig.sync()


Let's begin with a basic jig that stores a value in a variable. Create a jig called SimpleStore. By extending from Jig, the instances of your class will automatically sync to the blockchain. Every jig has an owner. Any code may read jigs but only its owner can update it. The owner is typically a Bitcoin address, and the private key is required to update it.

In addition to owner, every jig has a location. A jig's location is the pairing of a Bitcoin transaction ID and an output index, and it represents a particular state in time of an object or class on Bitcoin. When you check the location property of a jig, you get its current location. If you wish to get the location where the jig was first deployed, that is called its origin. The origin is unique and will not change, however location changes with every update. After a method call, your jig will have a new location pointing to a Bitcoin transaction containing the last method call.

Loading Jigs

Loading all jigs

await run.inventory.sync()

const simpleStore = run.inventory.jigs.find(x => x instanceof SimpleStore)


Loading a specific jig

const specificJig = await run.load(simpleStore.location)


// Fast-forward the jig to its latest state
await specificJig.sync()

The simplest way to load your jigs is to call run.inventory.sync() and then access run.inventory.jigs. run.inventory.sync() will find and load all objects owned by run.owner and place them in the jigs array. Once loaded, you may call methods and use them normally. Alternatively, you may wish to load a particular jig or load a jig in a historical state. To do either, pass the location of the jig you wish to load into run.load().

If you've loaded a historical location so that your jig is in a previous state, you'll need to first catch up to the latest state before you'll be allowed to make a method call. sync() will handily fast-forward a jig to its latest state on the blockchain without triggering a Bitcoin transaction. In the example on the sidebar, if specificJig was in a historical state, you would call specificJig.sync() and then call specificJig.set('abc'). When you accidentally try to update a jig without the jig being in its latest state, Run will safely abort before publishing a Bitcoin transaction and inform you with an error. In that case, you'll just need to add the preceding sync() call and execute your code again. The best practice is to write code in such a way that jigs are always up-to-date in their latest state. Run manages the heavy lifting for you.

sync() also acts as a debugging tool since it surfaces any errors your jigs have after you've made changes to them. If you notice your app acting funny, a well-placed preceding specificJig.sync() can help you uncover the error. You may also call sync() on your Run instance, like this: run.sync(). That'll help you search out any errors from your entire app in all of the jigs you own.


Jigs are interactive objects on Bitcoin. You define a jig with a JavaScript class and that class determines exactly what the jig can do. All of your jigs are unique. Each one has an owner and only that owner can update the jig. How is that secured? Bitcoin! Let's explore how you create a jig.


class Post extends Jig { 
    init(message) {
        this.message = message

new Post('Hello, world')

Let's create a new class of jigs called Post to represent comments on a message board. In JavaScript, your class initializer is called constructor, but for jigs, this method is called init. Think of them the same way. If init throws an exception, the jig will never be created, just like constructors. You create jigs with the new keyword, just as you would with normal JavaScript objects, and they get deployed onto the Bitcoin network. Pretty cool.


class EditablePost extends Post {
    edit(message) {
        this.message = message

const editablePost = new EditablePost('Hello, world')

editablePost.edit('Hello, BitCoin')

Jigs are updated by calling methods. In fact, this is the only way to update jigs. Your jig class defines the ways that your jig instances may evolve, so be sure to think ahead. When you call a method, Run publishes a Bitcoin transaction with data in an op_return that includes the method name and its arguments. The state may be recomputed simply by playing back every update one-by-one. For more information about how it works, see How It Works.


class Dragon extends Jig {
  send(to) {
    this.owner = to

new Dragon().send(address)

Jigs may be sent to someone else by changing the owner property of a jig in a method. You can set the owner to a Bitcoin address, a public key, or a custom Lock. The new owner will be able to update the jig starting in the next transaction.


Wait for updates to complete

class LoyaltyCard extends Jig {
    init() { this.stamps = 0 }
    stamp() { this.stamps +=1 }

const card = new LoyaltyCard()
await card.sync()

await card.sync()

Sync a jig from its origin to its latest state

const card2 = await run.load(card.origin)

await card2.sync()

Run is asynchronous. When you create or update jigs, Run creates Bitcoin transactions for you in the background and broadcasts them to the network. As with any network request, the request may sometimes fail. Your connection may go down, or a node on the network may reject your transaction.

Every jig has sync() available to ensure your local state is the same as that on the network. Calling await jig.sync() returns when:

  1. All pending local transactions have been published successfully, and
  2. The jig has been caught up with any new transactions from the network.

Any errors in validation or network requests will throw an error.

When testing ideas out in the browser, you won't need to call sync() very much. Run will happily execute method calls on jigs in their latest state. However, in a production app, the best practice is to call sync() after every method call to ensure that you catch errors early and handle them gracefully. Calling sync() will force any error to show up at that particular line in the code.

Run updates your jig's state with each method call you make. However, it does not continuously update your jigs with the blockchain. Because if it did, as a developer you'd feel like you were on shifting sand. Instead, you've got a reliable and steady state for each jig that you're working with. Therefore, depending on the app you've built and actions of the owner of the jig, you might need to catch up a jig to its latest state because it could have been modified outside of your app.


class Event extends Jig {
  createTicket() { return new Ticket(this) }

class Ticket extends Jig {
  init(event) { this.event = event }

Event.deps = { Ticket }

Jigs are designed to interact together. Jigs may create other jigs, call methods on other jigs, read properties on other jigs, and even store other jigs inside them. These are just a few of the types of interactions that Run supports.

Calling new to construct a jig within a method of another jig will create a new output in the transaction. Sometimes you will create new jigs that are of the same class, but other times you will want to create jigs that are of a different class. Because Jig code runs in a sandbox without access to other code, you set the deps property on your jig class to tell Run about any other classes you use. These dependencies will be made available as globals to your jig.

Jigs may store other jigs as properties too. Think of these as standard JavaScript object references that you may read or write. However, if stored jigs are updated by calling methods, then their owners must also sign the Bitcoin transaction that updates their state. For more information about when owners need to approve, see the Ownership Rules.


Destroy a jig


Override destroy to finalize a jig

class GiftCard extends Jig {
  init(value) {
    this.value = value

  destroy() {
    this.value = 0

Not all jigs will live forever. You may need to clean up old jigs in your inventory, and or you may need to have one jig consume another jig to make an update. Calling destroy() on a jig creates a transaction that removes the jig's output and makes it un-updatable. To do this, a jig may be destroyed. When a jig is destroyed, it no longer has an unspent output on the blockchain, and it will not appear in your inventory.

Destroyed jigs still have unique locations that identify their final state. You can even still load their final state using run.load(). However, destroyed jigs are marked as being destroyed with a null owner and they are forever locked in their final state.

By default, every jig has a destroy method. If you wish to prevent a jig from being destroyed, override the destroy method and throw an error in it. You can call destroy from outside the jig or from another method. You can also override destroy() to put the jig into its final state.


class Tip extends Jig {
  init(message, pubkey, amount) {
    this.message = message
    this.owner = pubkey
    this.satoshis = amount

  withdraw() {
    this.satoshis = 0

new Tip('I like your videos', pubkey, 100000)

Jigs may be backed by bitcoins. When a jig is backed, it means that the output associated with that jig has a non-dust value in it. Backed jigs let users send money between each other and provide a baseline value for items. To back a jig, set the satoshis property to a number in a method. Your purse will automatically deposit that amount into the jig. When the satoshis property is later decreased, those Bitcoins will be withdrawn to the active purse.

It is important to remember that backed jigs may be melted at any time by spending the jig output outside of Run. This will destroy the jig, and the owner will keep the satoshis.

Checking Parameters

Attaching an item

class Hat extends Jig { }

class Person extends Jig {
  wear(item) {

    this.item = item

Person.deps = { Hat, expect: Run.extra.expect }

You should always check the parameters passed to your methods. If you are expecting a number, make sure it is really a number. If you are expecting a jig, then make sure you have a jig of the right class. This prevents others from mis-using your jigs.

For your convenience, Run provides the expect sidekick. expect lets you make assertions similar to those you might be familiar with in Jest or Chai. You can to check many things, including if a jig is a certain class, if a number is greater than another number, or if a parameter is of a certain type. To get started, add expect as a dependency to your jig class. Then, check out the expect documention to find the right assertion.

Sometimes you may wish to check if a class is part of a changing set. For example, a game may have a list of item classes that may change over time. This is a little more advanced. See the Dynamic Whitelists section.

Attaching Media

class DinoPet extends Jig { }

DinoPet.metadata = {
  emoji: '🦖',
  image: 'b://55e2c09672355e009e4727c2365fb61d12c69add91215ee3e9f50aa76c808536'

new DinoPet()

You may optionally set an icon onto a jig using an emoji, a custom image, or both. These icons will show in explorers, exchanges, and wallets, whenever your jig is displayed. To attach an icon, you set the metadata property on your jig class and then this icon will apply to all instances of that class. You can also set rich media like audio and 3D models too.

Setting an emoji: To add an emoji, set the emoji field on metadata to a single emoji character. You can find an appropriate emoji on Emojipedia.

Setting an image: To set an image, first upload your image on-chain in the B:// protocol format. Easy-B is an excellent tool for this. The image data you uploaded can then be referenced using a string that starts with b:// and includes the transaction ID. Currently Run supports SVG, PNG, and GIF formats. SVG is recommended in most cases because it scales up better on large displays and loads quicker due to its smaller file size.

Setting audio: To add an audio file, set a b:// protocol uri into the audio field in the metadata object similar to images.

Setting a 3d model: To add a 3d model, set a b:// protocol URI to the glbModel field in the metadata object similar to images.

For more information, see the section on Standard Metadata.


With Run, you can own code, like classes and functions, just as easily as you can own objects. This may sound a little meta at first, but don't worry — you've been doing it all along! Every jig you created was linked to a jig class which you owned too. That jig class lived in its own output and had its own location.

When you own a piece of code, it means you have control over that behavior. For example, if you own a jig class, you get to decide what its jig instances are able to do. You can update or destroy that class and even call methods on it. Run calls classes and functions that people own Code with a capital C. Using Code, you can define new kinds of jigs, create reusable helper functions, share your server logic for auditability, discover algorithms from other apps, and much more.

There are two kinds of Code that Run supports:

  1. Jig classes: Jig classes are classes that extend from Jig and behave like jigs. You already know these. You can use them to create jig objects as we've already seen, but you can also call methods on them to update their properties over time. Jig classes evolve according to same Ownership Rules as jig objects.

  2. Sidekicks: Sidekicks are your helpers. They are your classes or functions that don't extend from Jig which you use more for supporting roles. You might use sidekicks to create a custom lock, to define a berry, to make a shared helper like expect, or even to store your server code on-chain. When you call a method on a sidekick, nothing gets recorded to Bitcoin. But you can call sidekicks from inside jigs and even from your own app. There are no restrictions on what kinds of parameters can be passed into or returned from sidekicks.

Using jig classes and sidekicks, you have a powerful repertoire to build extensible apps.


Deploy a sidekick function

function sha256(data) { ... }

const sha256Code = run.deploy(sha256)

await sha256Code.sync()

You deploy your classes and functions to Bitcoin. Deploying uploads your code in a Bitcoin transaction and creates a new output for it that you own. To deploy, you call run.deploy() and pass in your local class or function. Run will publish the transaction in the background and make you the owner of the new Code. Being the owner allows you to perform actions on it. Code is not necessarily static, as we'll see.

run.deploy() returns to you a new copy of your class or function that you should use going forward. This copy is special: unlike your original code, this copy is linked to your new Bitcoin output. It is also securely sandboxed and acquires several special Code methods that you can use to update it. We suggest adding the word Code to the name of the copy to differentiate it from your local class. You can call sync() on it right away to make sure that it deployed successfully.

We recommend you deploy all of your code in advance and load your load when your app starts. This way, your app and your users have a stable library to work with. You can do this by writing a script outside of your app.


Load a Data class

const Data = await run.load('<class-location-goes-here>')

const data = new Data('abc')

Find a class you own in the inventory

await run.inventory.sync()

const MyClass = run.inventory.code.find(C => C.origin === myClassOrigin)

You will want to load the code your deployed when your app starts. run.load(), in addition to loading jigs, is able to download, install and sandbox your classes and functions from the blockchain too. Just pass in the location of the code you wish to download.

Alternatively, you can use the inventory to find your code. run.inventory.sync() will load all the code that you own and place it in the run.inventory.code array. You can filter that array by origin to find the code you plan to use.


Deploy a jig class with a dependency

class Reward extends Jig { ... }

class LootBox extends Jig {
  init() { this.reward = new Reward() }

LootBox.deps = { Reward }


You can create code on Bitcoin that uses other code on Bitcoin, just like you would in your application. To do this, you have to explicitely tell Run that you are using other classes or functions, because Run needs to be able to link the code together.

You tell Run about other code you use by setting the deps property on your class or function. The deps property should be set to an object having all of the code you use inside. Those dependencies stored in deps will be made available as globals inside your class or function.


class EditablePost extends Post {
  edit(message) {
    this.message = message

You can create hierarchies of jig classes using Run. This is often useful for adding or changing some base class behavior. For example, think of a game where a base Vehicle class is extended to create many types of vehicles, like planes and trains.

To extend a class, you use the extends keyword as you normally would in JavaScript. When you deploy an extension class, Run will automatically create separate outputs for both the parent and the child and link them together. You do not need to add the parent class to the deps object on the child. Run is smart enough to automatically find the parent.

Inside methods on the child class, you can call the parent class's methods by using the super keyword in JavaScript. This is useful when you want to override a method on the parent to add behavior but you still want to call the parent method inside.

By default, extending a class requires the parent class's approval. This ensures the instanceof keyword is secure, because if Run didn't require parent class approval, third-parties could extend from a class to trick your instanceof checks into passing. Sometimes, however, you will want third-parties to extend your classes, and in those cases, set the sealed property on your class to false before you deploy so that anyone can create extensions.


Load a class at its origin and fast-forward it to its latest state

const DigitalPet = await run.load('<digital-pet-class-origin>')

await DigitalPet.sync()

When you call MyClass.sync(), it works just like myJig.sync(). If there are pending transactions, they will be published to the blockchain, and if there are network updates you haven't received, Run will download and apply them. We always recommend calling sync() after every code update to catch errors too, just like jigs. If you load a class by its origin, it is best to call sync() right after to make sure you have the latest state. For more about syncing, see Jigs: Syncing.


class Weapon extends Jig {
  static setPower(power) {
    this.power = power

const WeaponCode = run.deploy(Weapon)


// WeaponCode.power === 100

You can call methods on jig classes just like jig objects. Class methods can change properties, call other class methods, and create instances. You can even send the code to someone else by changing its owner!

To write a jig class method, put static before the method name and it will apply to the class itself and not instances. When you call a class method, Run publishes a Bitcoin transaction with the update and assigns the code to a new location. Other jigs that use the code will see the updates when they sync.

You should think of code as living objects with their own history. Although only jig classes can have static methods that update their state, all code including sidekicks can be upgraded, destroyed, and authed.


const OldWeapon = await run.load('<weapon-class-location>')

const NewWeapon = class Weapon extends Jig {

// Copy over existing state
Object.assign(NewWeapon, OldWeapon)

// Except the bindings, which are set by Run
['origin', 'location', 'nonce', 'owner', 'satoshis'].forEach(x => { delete NewWeapon[x] })


await OldWeapon.sync()

After your code is deployed, you may discover that it is missing an important feature or perhaps has a bug. On other blockchains, this is a terminal failure, but in Run, you can call upgrade() on your code and pass in a replacement class or function. That replacement will become the new behavior. Existing jigs that were deployed using your old class will get the upgrade when they sync or when they interact with another jig that already has the upgrade.

To upgrade a class:

  1. Load the old class
  2. Write the new class, including all existing methods
  3. Copy over existing state to the new class, except the bindings
  4. Call OldClass.upgrade(NewClass) and sync

We recommend writing a script to upgrade, similar to deploying code. It is important when you upgrade to copy over every property and method to the new class, because you are defining a full replacement. The example on the right shows a safe way to copy over state.

After you upgrade a jig class, you'll want to sync its jig instances when you load them in your app to make sure they get the upgrade. One way to do this is to call jig.constructor.sync() after loading any jig, but if there are many updates this might not be very efficient. Instead, we recommend calling Run.util.unify(jig, LatestClass). This will instantly upgrade the jig to use the latest version of a class that you already know about.

If you wish to provably prevent upgrades, you can set upgradable to false on the class. This is useful if you wish to show others that your code will not fundamentally change.

With great power comes great responsibility! Be careful.


// Trust the class'<your-class-origin-txid>')

// Trust an upgrade'<your-class-upgrade-location-txid>')

Code needs to be trusted in order for Run to load it. To load a jig, its class has to be trusted too, since that defines its behavior. This keeps your application secure by ensuring you do not accidentally load harmful code. All code that Run executes, includes deployed classes, upgraded classes, and any linked code you used in deps, needs to be trusted.

To trust code, you call and pass in the transaction ID where the code was deployed or upgraded. Be careful to just pass the transaction ID and not the code's location. If you try to load a jig but not all of its code is trusted, you may see an error saying "Cannot load untrusted code". You can get the untrusted txid out of the error object, trust it if it's safe, and retry the load again.

It is possible to trust any code in your Cache by passing "state" into This is a good idea when you are building the cache yourself because it will lead to better performance.

It is also possible to trust all code by passing "*" into This is strongly discouraged for production applications, but it can be useful during development and testing.


Using jigs, you can create tokens similar to ERC-20. These can be used for stablecoins, in-game currencies, tradable reward points, shares of stock, and more. Unlike ERC-20 however, where different users interact through a smart contract, in Run each user owns their own tokens. This makes them more like native bitcoin.

In Run, tokens are just jigs that are fungible, meaning that you can divide them into smaller pieces and combine them back together, like cash. Tokens can be minted, owned, sent, and redeemed. And while you could write your own token class to implement this functionality, Run provides a base Token standard for your convenience. You extend from Token to create your own fungible token. As the owner of the class, only you will be able to mint new coins for your users.

Here we will guide you through a few use cases. For more, see API Reference: Token.


Deploy a new token class

const run = new Run({ owner })

// Define the token class
class USDCoin extends Token { }
USDCoin.decimals = 6
USDCoin.symbol = 'USDC'
USDCoin.metadata = { emoji: '💵' }
USDCoin.backingBank = 'HSBC'

// Deploy
await run.sync()

// Write this down

You can define your own tradable token by creating a class that extends from Token. Your extension uniquely identifies your token and it will have its own name and properties. You don't need to add any methods either — all of the most common functionality for tokens is already in the base class. You will however probably want to set a few properties: like symbol, decimals, metadata, and anything particular to your token. Make sure to check out the Standard Metadata section for metadata used by wallets and exchanges.

Next, deploy your class. To do this, call run.deploy() in a script. Be sure to write down its location afterward, and make sure you've deployed it using an appropriate owner. You mint new tokens through the class, so its owner should be very secure. You may assign your token class to a private key or a more complex ownership script. Consider assigning your class to a Group lock to require multiple parties to sign off for mints.


// Load and sync your token class
const USDCoin = await run.load(tokenClassLocation)
await USDCoin.sync()

// Mint new coins to users. Only USDCoin.owner may do this
const mintedCoin =, address)
await mintedCoin.sync()

console.log(mintedCoin.amount) // 100

Minting tokens is as simple as calling mint() on your token class. You pass in the amount of tokens to mint along with the address to mint to. If you don't specify an address, you will mint tokens to the class owner.

Every time you mint, your token class is spent and the class receives a new location. One best practice is to the save the location for your token class after every mint. This way, Run can load it quickly the next time. When you load the exact latest location of the class, Run can get it from its cache. When you load from an older location, sync() will take some time to catch up.

You can mint to several users in a single transaction. Just wrap all your mint() calls inside of a run.transaction().


Send some of a coin and keep the change

const sentCoin = coinToSend.send(pubkey, 30)

Send to two users in the same transaction

run.transaction(() => {
  coinToSend.send(savanna, 10)
  coinToSend.send(margot, 20)

await run.sync()

Users that own your tokens can freely send them to others. To send a token, simply call send() and pass in the new owner and the amount to send. If you don't specify an amount, then the whole token amount will be sent. The return value of send() is the new coin that was sent. The change will remain in the current token.

You can send to several users in a single transaction by wrapping all your send() calls inside of a run.transaction().


Combine three tokens together

firstToken.combine(secondToken, thirdToken)

Combine and send in a single transaction

const tokens = run.inventory.jigs.filter(jig => jig instanceof USDCoin)

const tx = new Run.Transaction()
tx.update(() => tokens[0].combine(...tokens.slice(1)))
tx.update(() => tokens[0].send(amount, address))
await tx.publish()

After users have received several tokens, each of the same class, they can convert them into a single token having the combined amount using the combine() method. This is like taking five twenty-dollar bills to the bank to receive one one-hundred dollar bill. To combine tokens, call the combine() method on one token and pass in the other tokens that should be merged into it.

It is best if apps and wallets combine tokens regularly to minimize the number of objects that need to be loaded. One best practice to to combine before every send. You can even combine and send in a single transaction, as seen over there. ⇥


Redeem a token as bitcoin

const sender = token.sender
const satoshiValue = tokensToSatoshis(token.amount)

class Payment extends Jig {
  init(owner, satoshis) {
    this.owner = owner
    this.satoshis = satoshis

run.transaction(() => {
  new Payment(sender, satoshiValue)

await run.sync()

As an issuer, you may need to redeem tokens back for their underlying asset. For example, a stablecoin might be redeemed into its backing currency. Every token has a sender property that stores the last owner of that particular token. You can use this to determine who to redeem to.

Usually, you'd run a server that would monitor a redeem address. Users would send their tokens to that address, and when you receive a token, you'd use the sender property on it to send the underlying asset. Then you can destroy that token so that it is no longer in circulation.

Limiting Supply

class CollectableCoin extends Token {
  static mint(amount, to) {
    if ( + amount > {
      throw new Error('Cannot mint: Max supply reached')

    return, to)
} = 10000
CollectableCoin.upgradable = false

You may want to limit the supply of a token. You can call destroy() on your token class after you've minted all tokens. This will prevent any further mints. It's a good idea for when you don't know in advance how many tokens you will mint. Calling destroy also prevents new tokens from being created in your name even if your private owner key were to get hacked.

Another approach is to set a max supply for a token by overriding the mint() method to track the number of coins minted, as seen to the right. Notice that the upgradable property is set to false; this prevents upgrades to your class that would to remove this check. This creates a provably limited supply, and is a good idea for when you want to limit the supply in advance.


You may need to blacklist individual tokens. For example, a user may lose their keys and request that you reissue their tokens. Or law enforcement may come to you to request blacklisting if your tokens are being used illegally. In both cases, the recommended solution is to keep a list of token locations that are blacklisted and not redeem any token that is on that blacklist. You will need to track descendant UTXOs too and blacklist them as well. But stay tuned! A simpler solution is coming.


Run also offers a standalone library called Tokenkit that makes the process of deploying, minting and working with tokens breath-takingly simple. To find out more head over the to tokenkit github repo.

Advanced Usage

Standard Metadata

class DigitalPet extends Jig { }

DigitalPet.metadata = {
  author: 'Maximus',
  license: 'MIT',
  emoji: '🐉'


Wallets, explorers, and exchanges will want to show your jigs. You can add special metadata to any jig to help these apps and services do so. Metadata is stored as an object called metadata on your jig, code, or berry, which contains various properties. The following common properties are called standard metadata:


Property Type Description
name string String name to use in place of the class or function name
description string Short sentence, less than 80 characters, that describes the jig for users
emoji string Single UTF-8 emoji character to represent the jig
image string Reference to an SVG or PNG image stored using B://
audio string Reference to an audio file stored using B://
glbModel string Reference to GLB file representing a 3d model stored using B://

Attribution and Licensing

Property Type Description
author string markdown Name of the creator for the code or content
title string markdown Title of the content
source string markdown URL where the content was found
license string markdown License for the code or content

Media stored on-chain using the B:// protocol may be used as metadata for images, audio, or 3D models. To reference previously-uploaded data, use a string formatted either as "b://<txid>" or "b://<txid>_o<vout>". If vout is present, it must be zero-indexed. If it is not present, the first B output in the transaction is used. To upload B data, you may use the EasyB CLI tool.

You can start by setting these properties on your jig classes, as seen to the right. By convention, jig instances will automatically use the metadata from their class. However, jig instances may also have their own metadata that overrides its class metadata. You can put any information in metadata you deem important, even properties that are not listed above.

Batch Transactions

Use two jigs separately in one transaction

run.transaction(() => {
  new SomeJig()

await run.sync()

Multiple updates may be batched together in a single Bitcoin transaction. Batching makes the actions atomic, meaning all of them happen or none of them happen. This is great when two users want to exchange jigs, for example. If any errors occur while publishing the updates, all of the jig changes in the transaction will be reverted. Besides making updates atomic, batching also reduces fees.

Any number of updates may be batched together from different jigs. Call run.transaction() and pass in a callback function that includes all of the actions that you want batched together. Then call run.sync() to wait for the updates to publish. If you need more advanced transaction control, see the Transaction API

Owners must still sign off on any updates to a jig, so if you just created a jig in a new output, you can't yet call a method on it because its owner can't sign. If you just sent a jig to someone, they also can't use it until the next transaction.

Caller Variable

Storing the parent jig

class Child extends Jig {
  init() {
    this.parent = caller

Enforcing a method may only be called by certain classes

class Database extends Jig {
  init(rootUser) {
    this.rootUser = rootUser

  deleteAll() {
    if (caller !== this.rootUser) throw new Error('only the root user may delete the database')

class User extends Jig {
  deleteDatabase(database) {

Within code, there is a special caller variable that is available. This variable is always set to the jig or jig class that called the current method, or null if the current method was invoked from application code. Sidekicks are transparent and will never be a caller.

You can use caller to store a jig's creator, enforce that a jig may only be created by a specific parent, or create administrator jigs that uniquely can call special methods.

Limiting Interactivity

Create a token that can only interact with itself

class MoneyBucks extends Token { }

MoneyBucks.interactive = false


By default, any jig may interact with any other jig in a transaction. Jigs may be atomically swapped, stored on each other, created from each other, and more. However, the downside is that when jigs interact with other jigs, all of the code for those other jigs needs to be trusted by anyone who wishes to load those jigs later. Run maintains a global trust list, but apps and token issuers may want to avoid the risk that there jigs may be un-loadable by restricting their code and jig instances so that they can only interact with certain other jigs. This removes the risk that a jig might not be redeemable by a service after it interacts with other code that the service doesn't yet trust.

To limit interactivity, you can set the interactive property on your class or function to false. When code is non-interactive, it can only interact with itself, its instances, and any references it has to other code. Run enforces this.


To customize interactivity on classes with interactive = false, a convention to allow which Code your jigs can interact with is setting a friends array on the class definition.

Additionally, you may want to customize friends in the future, so implementing a static method to set friends after the initial deployment is a good idea.

class MoneyCoin extends Token {
  static setFriends(friends) {
    this.friends = friends;

MoneyCoin.friends = [friendsClass];

Private Properties

class TradingCard extends Jig {
  send(to) {
    this.owner = to

  _checkNotBlacklisted(owner) {
    if (TradingCard.blacklist.includes(owner)) {
      throw new Error('blacklisted')

TradingCard.blacklist = [cheaterAddress]

Jigs may have private methods and private properties.

Private methods are useful when you have internal helper methods that shouldn't be called from outside. To make a method private, you put an underscore before the method name. When a method is private, it can only be called by the current jig, a jig of the same class, or the jig class itself. If a different jig attempts to call a private method, Run will throw an error.

Run supports private properties too. Like methods, you put an underscore before the property name to make it private. You can use private properties to hide state that shouldn't be used by other jigs. Private properties may only be read from inside the current jig, from a jig of the same class, or from the class itself. If you try to access a private property from another class, Run will throw an error.

Auth Method

Limit the creation of jig instances by forcing the class to auth

class SingleTonMonster extends Jig {
  init() {

Every jig and every code has an auth() method on it. To auth means to spend a jig, forcing its owner to approve of any actions performed. Auth also ensures that the jig's state is the latest. You may use auth() for many purposes, such as to have a class approve of the creation of instances, as seen to the right. You may also use it to get approval from several jigs before performing some action. For example, you may require that several players in a game auth using their characters for some shared action to take place, like moving on to the next round. Authing is a fundamental action that will become more useful to you over time.

Code Presets

class Dragon extends Jig {
  set(name) { = name

Dragon.presets = {
  main: {
    origin: 'bee45c75c37a289517f33ebfa051601c9610ccc56fbddfbabc44413db5b0bc1b_o1',
    location: 'bee45c75c37a289517f33ebfa051601c9610ccc56fbddfbabc44413db5b0bc1b_o1',
    nonce: 1,
    owner: '13amCautaFqwbWV6MoC86xrh96W4fXGfDV',
    satoshis: 0

When you wish to create an instance of a jig from a class you've already deployed, you have two options. Either you can load the class from the blockchain via run.load() and then create an instance, or you can create an instance from a local class that has presets applied. When a local class has presets, Run doesn't have to download the code from the blockchain. Presets are a great way to share jig classes in NPM libraries.

You can use presets by uploading your code to each Bitcoin network you wish to support using run.deploy() in a script. The presets are origin, location, nonce, owner, and satoshis set onto a presets object for the given network. Run will detect these presets and automatically use the origins and locations on the appropriate network.


Load a metanet node

const txid = '2f24d7edb8de0ef534d8e0bc2413eddda451b4accc481519a1647d7af79d8e88'
const node = await MetanetNode.load(txid)

Define the MetanetNode Berry

class MetanetNode extends Berry {
  // Its constructor can only be called by its pluck function. Run guarantees this.
  init(pnode, parent, data) {
    this.pnode = pnode
    this.parent = parent = data

  // Run calls this pluck function when you call run.load with a Berry class.
  static async pluck(location, fetch) {
    const data = txo(await fetch(location))

    if (data.out[0].s1 === 'meta') {
      const pnode = data.out[0].s2
      const txidParent = data.out[0].s3
      const data = data.out[0].s4

      if (data === 'METANET_ROOT') {
        return new MetanetNode(pnode, null, data)
      } else {
        const parentNode = await MetanetNode.load(txidParent)
        return new MetanetNode(pnode, parentNode, data)

MetanetNode.deps = { txo: Run.extra.txo }

Third-party protocols, like Twetch, B, and Metanet, may be used in Run as berries. Berries are JavaScript objects that deterministically capture data on the blockchain that is outside Run. If you can write code to parse an OP_RETURN, you can create Berries. Berries are more than data though. They are typed objects with methods, and they may be passed into jigs, stored as properties, cached, and more.

To load berries using an existing Berry class, you call BerryClass.load() and pass in the path to load, which is often a transaction ID. Run ships with one berry class, B, that may be used to load B:// protocol data.

To define a new Berry protocol, you create a class that extends from the base Berry class and implement the static pluck() method and init() method. Run calls your pluck() method to load data for that path into a JavaScript object. The second parameter to pluck is a method that allows you to fetch transactions from the blockchain. Run fetches transaction data in raw hex format, but you can parse it using the txo or Tx helpers. In pluck(), you instantiate a berry, which will call your init() method.

Once loaded, berries have locations just like jigs. Berry locations are slightly more advanced though and include the class location, the path, and more, in the form: <berry_class_location>?berry=<path>&hash=<state-hash>&version=<protocol>. This is a unique identifier that allows them to be safely referenced and cached.


Send a token to a P2PK output script

class PubkeyLock {
  constructor(pubkey) { this.pubkey = pubkey }
  script() { return asm(`${this.pubkey} OP_CHECKSIG`) }
  domain() { return 74 }

PubkeyLock.deps = { asm }

token.send(new PubkeyLock(pubkey))

A provably unspendable lock

class Unspendable {
  script() { return asm('OP_RETURN') }
  domain() { return 0 }

Unspendable.deps = { asm }

The default owner for a jig is a Bitcoin address. This is a great default, but sometimes you'll want more advanced ownership. For example, you may want a group to own a jig, so that no one party has exclusive control. Or you may wish for a jig to be provably owned by nobody. Both of these and more are possible with locks.

A lock is an object that produces a Bitcoin output script. You can set one as the owner on your jigs. Run ships with a Group lock class for multi-sig ownership, and you may also create your own locks by implementing the Lock API. Your lock class will have two methods: script() and domain(). script() returns the bitcoin output script in hex format, and should be safe to call with any state. domain() returns the maximum size of the unlocking script for this lock. After implementing these methods, you set the owner of a jig to an instance of your lock, and Run will build its transaction output.

You'll probably also want to unlock your jigs to update them. To do that, create a corresponding key by implementing the Owner API. Your implementation of the Owner API requires two methods: sign() and nextOwner().

Locks are deterministic, typed, and run in a sandbox environment. This means they can be safely used inside jigs. But this also means they can't use the bsv library or similar external code. Run provides an asm helper function to fill the gap when building custom scripts inside Lock classes.

Tips and Tricks

Limiting Supply

class Weapon extends Jig {
  init(owner) {
    // Only the Weapon class can mint Weapon jigs

    this.owner = owner

  static mint() {
    if ( >= 10) throw new Error('too many weapons')

    // The class keeps track of the number of mints

    return new Weapon()
} = 0

Weapon.deps = { expect: Run.extra.expect }

const weapon =

The supply of a jig class may be limited through the use of a minter. The minter is a separate jig or jig class that regulates the number of mintee jigs produced. In the example on the right, the Weapon jig class is the minter for its own instances. We use the special caller variable to enforce that Weapon jigs may only be created through the class's mint() method. If a player tried to create a Weapon instance using new Weapon() outside of mint(), Run would throw an error because the caller property would be null.

Random Numbers

Use an oracle to provide random values

class RandomValue {
  init() {
    this.owner = ORACLE_ADDRESS
    this.satoshis = 1000

  set(value) {
    this.value = value
    this.satoshis = 0

class DigitalPet {
  init() {
    this.random = new RandomValue()

  setup() {
    this.size = this.random.value % 10
    this.agility = this.random.value % 100
    this.color = this.random.value % 5

DigitalPet.deps = { RandomValue }

Many applications use random numbers to perform updates. For example, you might wish to randomly generate the properties of a digital pet when it is created, or you may wish to determine the winner of a game using a statistical calculation. Generating random numbers inside jigs can be challenging because blockchains have to be deterministic. Run disables the Math.random() function within jigs for this reason.

It may be tempting to use the location or origin properties of a jig as random numbers. Certainly, they appear random. However, this is a bad idea because a motivated user would be able to make alterations to their Bitcoin transactions, either during signing or payment, until they get the location or origin that leads to the random value they want.

Instead, we recommended using an oracle to provide randomness. Jigs that require random values would send a paid request to an oracle service. This oracle service would set the random number on the request jigs it receives, and when the original jig that requires randomness is synced, it will get the random value.

This same idea also applies to other oracle data, including dates, prices, and more.

Dynamic Whitelists

A dynamic whitelist to support new tokens over time

class SupportedClasses {
  init() { this.classes = new Set() }
  add(T) { this.classes.add(T) }

const whitelist = new SupportedClasses()

class Game {
  init() { this.items = new Set() }

  use(jig) {


Account.whitelist = whitelist 

An app may want to allow third-party developers to create new classes of jigs. Those jigs can freely interact with existing jigs once approved. For this, you can create a dynamic whitelist of approved classes that jigs can check. See the example to the right 🠮

Atomic Swaps

Atomically swapping two items with different owners

Machine 1

const mine = await run.load(myLocation)
const theirs = await run.load(theirLocation)

const me = mine.owner
const them = theirs.owner

const tx = new Run.Transaction()
tx.update(() => mine.send(them))
tx.update(() => theirs.send(me))
const rawtx = await tx.export()

Machine 2

const tx = await run.import(rawtx)

if (tx.outputs.length) {
  // TODO: Inspect the transaction to be sure it atomically swaps

await tx.publish({ pay: false })

Run supports atomically updating jigs with different owners using the Transaction API. One use case for this is atomic swaps, where two jigs owned by different users are exchanged in a single transaction.

The general process for an atomic swap is for one user to start a Run transaction by calling new Run.Transaction(). Then, this user performs all updates inside an update() call on the transaction, including calling methods on jigs they don't currently own. Run allows this user to build the transaction even if they won't be able to sign for every jig. Finally, this first user calls tx.export() to export the transaction, which will pay and sign for it in the process.

The transaction is now built and must now be handed to other parties for them to sign. The other party then calls run.import() to load the transaction they received. They may then want to check the transaction by inspecting tx.outputs and Run.util.metadata. If they approve, then they may call tx.publish() to sign and publish. If more signatures are needed, they can export the transaction instead of publishing.

The Transaction API may also be used to simulate state channels and propose changes to other jigs. See the Transaction API for more information.

Custom purses

Invisible Money Button

MoneyButton provides a simple module to fund arbitrary bitcoin transactions using Invisible Money Button.

In a web browser, include the following script tag:

<script src=""></script>

Example setup in the browser:

const getPermissionForCurrentUser = () => { return localStorage.token }

const savePermissionToken = token => { localStorage.setItem('token', token) }

const imb = new moneyButton.IMB({
    clientIdentifier: 'your-moneybutton-client-identifier',
    permission: getPermissionForCurrentUser(),
    onNewPermissionGranted: token => savePermissionToken(token)

const purse = new MoneyButtonPurse.MBPurse(imb, bsv);

const run = new Run({
    owner: 'your-owner-private-key',

Upon setup and granting permission to Invisible Money Button, when creating Run transactions, the user's MoneyButton wallet will be used to pay for the transactions.


Paypresto is a service that can be used to pay for data and/or custom Bitcoin transactions with any BSV wallet.

In a web browser, include the following scripts:

<script src="//"></script>
<script src="//"></script>
<script src="//"></script>

Instantiate the Run instance:

const { Presto, embed } = Paypresto;

var payment;

class payPresto {
    async pay(rawtx, parents) {
        // process the raw transaction, outputs and UTXOs
    payment = Presto.create({
      key: ephemeralPrivateKey, // Ephemeral private key used to create the first transaction
      outputs, // include Run OP_RETURN payload, jigs, and change outputs
    .on('funded', async(payment) => {
        // sign Run inputs here, get raw transaction and broadcast to the Bitcoin network
    .on('error', err => { console.log('Error: ', err) });

const presto = new payPresto();

const run = new Run({
  purse: presto

When creating any Run transactions the Paypresto widget will display allowing the user to pay for the Run transactions with a wallet of their choosing.

Using Run on a Server

You may want to use Run on your server. For example, to:

Run is designed to work in a Node.js server as easily as a web browser. You might create a REST API using express that allows users to make queries. Or you might deploy a serverless function that responds to events. Or you might listen to relevant transactions using WhatsOnChain's SSE events to perform actions automatically. Run supports all of these architectures.

Run requires at least version 10 of Node. You can check which version you are using with node --version. If you are using Google Functions, be sure to set { "engine": 10 } in your package.json since it defaults to Node 8.

Here are a few more tips:

Expand the In-Memory Cache

Increase the state cache size

run.cache.sizeMB = 1000

The LocalCache stores jig state and blockchain transactions in memory. It is the default cache used by Run when running in Node. By default, it caches 10MB of data in memory. You can increase this by setting run.cache.sizeMB. The local in-memory cache is useful and compliments a persisted cache.

Increase Node Memory Limits

You may need to increase Node's memory limits if you have many jigs loaded or cached at once. If you launch your server by running a node process, you can increase its memory via: node --max-old-space-size=8192.

Persist the Cache

Save state into a Firestore collection

class Firestore {
  async get(key) {
    // Firestore does not allow forward slashes in keys
    key = key.split('://').join('-')

    const entry = await db.collection('state').doc(key).get()

    if (entry.exists) return

  async set(key, value) {
    // Firestore does not allow forward slashes in keys
    key = key.split('://').join('-')

    return db.collection('state').doc(key).set(value)

const run = new Run({ cache: new Firestore() })

It is a very good idea to persist your cache in a database so your backend never needs to load the same jig twice. It is even more important when using multiple servers because you can share this database. Simply implement the Cache API.

Run will automatically call get on your Cache implementation when values are needed, and set when values are ready to be cached. Cached values will never change for a given key. Just implement these two methods to load and save the cache into your preferred key-value database: Redis, Firestore, DynamoDB, etc.

To the right is an example of persisting in Google Firestore. You may want to modify it so that it also checks an in-memory local cache first and then goes to Firestore if that misses.

Avoid Race Conditions

If you are seeing server errors about Missing inputs or txn-mempool-conflict, it is likely that you have encountered a race condition. Two pieces of code are likely attempting to update the same jig at the same time, and are attemping to spend the same Bitcoin outputs. The network can only accept one. To solve this, here are a few recommendations:

Load jigs once at the start: If you have jigs you are reused across many request handlers, like a class that you mint from, load those jigs or code once upon starting your server rather than each time they are used. This will let Run track the output correctly between asyncronous calls, and successive updates on that object will be performed in the right order.

Separate server, separate purses: Every Run instance has its own internal update queue, so it is unlikely that the purse will be double-spent on a single server. But on multiple servers, if a purse key is shared, then it is very likely that double-spend errors will occur. To avoid this, use different purse keys on different servers.

Sync after every update: Call await jig.sync() on jigs after you call a method to be sure that the updates were applied before continuing on.

Serialize shared updates: If a request handler makes updates to multiple jigs, and these updates can conflict if interleaved across multiple users, then consider serializing these updates. Within a single request handler, you can bundle all jig updates together in a batch, so that the operation is all-or-nothing. Across multiple request handlers, you can put updates into a task queue like p-limit.

Add retry logic: If the above changes do not fix a race condition, consider adding retry logic. Run will retry network calls, but race conditions require manual handling by your server.

Load Only Safe Code

Even with sandboxing, arbitrary code has the potential for infinite loops and infinite memory attacks that can take down your server. Avoid running code that you do not trust. You should only add transaction IDs to your trusted set that you know are safe. Also, it is generally not recommended to call run.inventory.sync() on servers, because that will load UTXOs you receive from others.


Sometimes you will be faced with errors you don't understand. Don't fret! Here are some tips:

Writing Unit Tests

It is always a good idea to write unit tests for your jigs. We recommend using a framework like mocha or jest, and running your tests using the mockchain. The mockchain will be faster and will isolate your Jig logic from any network errors.

Getting Help

Please reach out to @runonbitcoin on Twitter or Twetch, or @niv in the BSV slack channels. We are happy to help you debug and fix any issues you encounter. If you can, see if you can reproduce the issue in the browser's web console.

How It Works


A jig is a JavaScript object that Run syncs with the blockchain. All of its code and method calls are stored on-chain in op_return metadata. Run can reconstruct the state of jigs by loading the code and replaying every method call, but usually intermediate states are cached by indexers. Most jigs are paired with a Bitcoin output so that only the owner of that output can make changes to the jig. All updates taken together form a transaction chain that enables consensus through user verification. This design is similar to other Layer-2 UTXO-based token systems because miners don't verify the JavaScript code. If anyone publishes an incorrect update, it not only destroys the jig but also leaves an immutable record.


Sample code for a transaction

class Dragon extends Jig { }

const dragon = new Dragon()

A transaction in Run is an atomic update to jigs or code.

        Inputs -> Computation -> Outputs

Inputs are the jigs and code which will be updated. Computation is stored as executable statements in an op_return. The Run Virtual Machine executes these statements and produces outputs which are the jigs and code updated or created fresh. The data for these jigs are not stored in Bitcoin outputs, but instead are stored in an off-chain cache and able to be recomputed by others from the blockchain data. In this way Run transactions are kept small. There may also be payment inputs and outputs too that are not used by Run but part of the transaction. Here is the transaction format for the example to the right:

Inputs Outputs
1. payment 1. op_return: RUN metadata
2. p2pkh: Dragon Class
3. p2pkh: dragon jig instance
4. change output for payment

Inspecting RUN metadata

const rawtx = await run.blockchain.fetch(txid)
const metadata = Run.util.metadata(rawtx)

The op_return data is made up of both push data and a JSON payload. It has the following structure:

[op_false] [op_return] 'run' <version> '<app-id>' '<json-payload>'

You can easily identify Run transactions and its outputs using the op_return metadata.

JSON Payload

Sample JSON payload

    "in": 0,
    "ref": [
    "out": [
    "del": [],
    "cre": [
    "exec": [
            "op": "DEPLOY",
            "data": ["class Dragon extends Jig { }", { "deps": { "Jig": { "$jig": 0 } } }]
            "op": "NEW",
            "data": [{ "$jig": 1 }, []]

The JSON payload stores Run-specific metadata. To the right is a JSON payload for the example above. Its fields are:

Name Description
in Number of jig and code inputs
ref Array of references to jigs and code used by not spent
out State hashes of jigs and code in transaction outputs
del State hashes of jigs and code deleted
cre New owners of jigs and code created
exec Statements to execute on the jigs

The exec field in particular contains the statements for Run to execute. There are 4 opcodes supported by the RUN protocol in 0.6:

Opcode Description Data Format
DEPLOY Upload new code [<src1>, <props1>, <src2>, <props2>, ...]
NEW Instantiate a jig [<jig class>, <args>]
CALL Call a method on a jig [<jig>, <method>, <args>]
UPGRADE Replace code with new code [<code>, <src>, <props>]

The state hashes used in the out and del arrays are calculated by taking the sha-256 of the JSON serialization of the jigs. This state cache format will also be documented soon. Finally, the Run VM provides certain native classes, like Jig and Code, that are built-in to its virtual machine. Eventually this virtual machine will be stored on-chain too ensuring total trustlessness.

The protocol will be documented more in a coming spec. Reach out for any questions!


Pass a sidekick object in by value

class Person {
    constructor(name, creationDate, profilePicture) { = name
        this.creationDate = creationDate
        this.profilePicture = profilePicture

    valid() { ... }

class SocialGroup extends Jig {
    constructor() { this.members = [] }

    add(person) {


SocialGroup.deps = { Person, expect }

const group = new SocialGroup()

group.add(new Person('Li', new Date(), null))

Every jig, every argument to a method, and every static property of a class, must be serialized so that it can be restored later. Run uses a custom serialization format that is similar to JSON. The following data types are supported:

All JavaScript IEEE 754 numbers types are serializable, including Infinity, NaN, and -0. Properties may be safely set on Sets, Maps, and Arrays, including any of the above types. Circular references are OK.

Symbols are not however serializable and will not be supported. Other JavaScript objects that are not currently supported include Date, WeakMap, Promise, Error, Float32Array, and BigInt.

Sidekick objects are JavaScript objects whose constructor is a sidekick class. Whereas jigs have blockchain locations and owners, and Run enforces that their state progresses from their method calls, sidekick objects are much simpler. They are stored by-value in their current state. A lock instance is an example of a sidekick object. In effect, they are data blobs with methods from on-chain code.


All Code is sandboxed so that it does not have access to your application code, including your private keys! This provides security and also determinism when replaying a jig's history because a jig should evaluate the same in every environment. Run uses Agoric SES, the gold standard in secure JavaScript evalution, combined with the vm library in node and hidden iframes in the browser, to perform this sandboxing. Despite this, it is recommended you avoid running untrusted code.

Safety Checks

Run also protects you from performing updates on your jigs that will not be valid by others. For example, Run will throw an error if you try to change a property on a jig directly rather than call a method, or if you attempt to set a function as a property on a jig. Only top-level method calls may change a jig's state which is also enforced by Run. In addition, every Run transaction is pre-verified before it is published on your local machine.

Ownership Rules

Jigs are special objects that have ownership rules which Run enforces. These include:

Likewise, without ownership, the above actions cannot be performed. Proving ownership requires spending a Bitcoin output, so when ownership changes on a jig, further updates to that jig must occur in a new transaction. There is also a fourth rule of ownership that is a right granted to all jigs:


All jigs and jig code are stored on-chain and are open for everyone to read. This enables anyone to reconstruct the state of any jig. Privacy is achieved similar to Bitcoin UTXOs. For maximum privacy, public keys should not be re-used. In the future, we will introduce private jigs that are visible only to the current owners, but by their nature, they will not work as well with explorers, analytics and other services.

Backwards Compatibility

Starting in Run 0.6, which uses protocol 0x05, all jigs will be backwards-compatible. This means jigs you launch today will always be supported into the future by the Run SDK. This is our promise. To keep this promise, every jig is connected to its protocol version, so as Run is updated, older jigs can be kept operational with their original behavior. In addition, we run tests against on-chain jigs with every update to ensure that your jigs continue to work.

API Reference


class Run { ... }

A Run instance coordinates activity between the application, its jigs and other creations, and the blockchain. You always create a Run instance when you use the Run SDK. This stores your settings, creates and signs transactions, loads jigs and code, connects to the blockchain network, securely sandboxes code, keeps an inventory of jigs, keeps a cache for fast loads, and more.


Create a Run instance on Mocknet. The purse will be auto-funded.

const run = new Run({ network: 'mock' })

Create a run instance on Testnet

// Create a run instance on testnet
const run = new Run({
  network: 'test',
  owner: 'cTMHbJULREfbsUFsuJLMrNbJ7VrASgWeYfFF6EgJMy49ARnNed3d',
  purse: 'cQP1h2zumWrCr2zxciuNeho61QUGtQ4zBKWFauk7WEhFb8kvjRTh'

constructor(options: object): Run

Creates a new Run instance.

The constructor takes many possible options, but the three most important options are network, owner, and purse. The network indicates which Bitcoin network to connect to. The owner and the purse are generally both private keys. The owner stores the user's jigs. Each live jig has a UTXO associated with it assigned to the owner's address. The purse is a separate private key used to pay the mining fees for Run transactions. It is best if the owner and purse are separate accounts so that jigs and money are kept in different wallets.

Creating a new Run instance will automatically assign it to Run.instance. You should only create one Run instance in your app.


Property Type Description Default
api string Either 'run' or 'whatsonchain'. Configures the blockchain and cache. 'run'
apiKey string Blockchain API key for WhatsOnChain. undefined
app string Application id to distinguish Run transactions. See How It Works. Empty string
blockchain Blockchain Blockchain implementation for interacting with the Bitcoin network. If specified, then network, api, and apiKey are ignored. RunConnect
cache Cache Cache API implementation that Run will use instead of the default NodeCache or BrowserCache
client boolean Whether to only load jigs from the cache and not replay transactions false
debug boolean Whether to enable verbose tracing and performance logs false
logger Logger Logging object for internal run messages. If logger is null, then nothing will be logged. You may pass console as the logger to log everything. Logs warnings and errors to the console
network string Bitcoin network, either main, test, stn, or mock. main
networkTimeout number Timeout for network requests in milliseconds 10000
networkRetries number Number of times to retry network requests 2
owner string or Owner Private key, public key, address, or custom lock used to own jigs and sign transactions Randomly generated LocalOwner
purse string or Purse Private key or Purse API used to pay for transactions. On the mock network, the purse will be funded automatically. For other networks, the user must fund the purse. Randomly generated LocalPurse
state State State API implementation that Run will use to load jigs efficiently StateServer or LocalState
timeout number Timeout for all Run actions in milliseconds 30000
trust Array<string> or '*' IDs of transactions whose code is known not to be malicious Empty array
wallet Owner and Purse A shorthand for a single object that implements both Owner and Purse. If specified, then owner and purse are ignored. undefined


Upload a BigInteger class to the blockchain

class BigInteger {
  // ...


await run.sync()

deploy(T: function): Code

Uploads code to the blockchain. Once deployment completes, the class or function will be assigned a location so that it may be downloaded later. It will also be assigned an origin and owner. deploy also sandboxes the class or function and returns it as Code with special Code methods. Code uploaded does not necessarily need to be a Jig class — any class or function will work.

import(rawtx, options)

Import a Run transaction to update it

const tx = await run.import(rawtx)

tx.update(() => run.deploy(AnotherClass))

const updated = await tx.export()

import(rawtx: string, options: ?object): Promise<Transaction>

Imports a Bitcoin transaction into a Run.Transaction object that can be updated.


Property Type Description Default
trust boolean Whether to automatically trust the transaction being imported false
txid string Optional transaction ID for the raw tx undefined

load(location, options)

Load a particular jig

const ticketLocation = 'afc557ef2970af0b5fb8bc1a70a320af425c7a45ca5d40eac78475109563c5f8_o1'
const ticket = await run.load(ticketLocation)

Load a code creation

const classLocation = 'e4a9618d3a187448feeb95ff30f7ec6381a025316cdcae2cdf388ad3de7fab6f_o2'
const MyClass = await run.load(classLocation)
const object = new MyClass()

load(location: string, options: ?object): Promise<Creation>

Universal load method to load any creation including jigs objects, jig classes, sidekick code, berries, and more. You pass in an on-chain location. The location is generally a transaction ID and output index pair. This string should usually be the jig's or class's last known location property. However, it is also possible to load jigs at any state in the past using other locations, although these will be read-only. Downloaded code will be safely sandboxed before being returned.


Property Type Description Default
trust boolean Whether to automatically trust the transaction being imported false


Wait for all jigs to deploy and classes to upload before continuing

class MyClass { }

class MyObject extends Jig { }
const jig = new MyObject()

await run.sync()

console.log('jig origin', jig.origin)
console.log('class origin', MyClass.origin)

sync(): Promise<void>

Returns a promise that completes when all pending transactions are published. After this completes, all jigs and classes will be assigned locations. Note: This method will not update the inventory with newly received UTXOs. For that, call run.inventory.sync().


Send two tokens and deploy a class all in the same transaction

run.transaction(() => {

transaction(f: function): any

Shorthand for creating a new transaction, calling update with the function passed, and then calling publish.


Trust a third-party transaction before loading its code

const codeTxId = codeLocation.slice(0, 64)

await run.load(codeLocation)

trust(txid: string)

Adds a transaction to the trusted set. All transactions that deploy or upgrade code must be trusted in order to load their jigs or code. By default, code that is not in the trusted set cannot be loaded. Make sure to pass a transaction ID and not a location.

There are two special values you can provide to trust(). If you pass "state", then any code in the Run cache or state provider is trusted. This will lead to performance improvements. If you pass "*", then all code is trusted regardless of where it comes from. This is dangerous for production but may make testing and development easier.


app: string

An ID to distinguish your Run transactions from other applications' transactions. Developers may set this in Run's constructor in order to find their specific transactions in third-party tools and analytics, like or WhatsOnChain. This string will be UTF-8 encoded and stored in the 5th chunk of the op_return script. For more details about the protocol, see How It Works.


Download a transaction from the blockchain

const txid = 'afc557ef2970af0b5fb8bc1a70a320af425c7a45ca5d40eac78475109563c5f8'
const tx = await run.blockchain.fetch(txid)

blockchain: Blockchain

Blockchain API to access the bitcoin network. See the Blockchain API. You may change the blockchain anytime.


cache: Cache

Cache API used to save and load existing state. You may change the cache anytime.


client: boolean

In client mode, jig and code may only be loaded if they are in the cache and Run will never execute transactions. This is useful if your cache is being populated via an external process that pre-loads relevant jigs. It adds a layer of protection and improves performance. The default value is false.


inventory: Inventory

Inventory that tracks creations owned by the current owner. This is reset whenever the owner changes.


logger: Logger

Logger implementation that prints out Run information. You may change the logger anytime.


networkRetries: number

Number of times to retry network requests if they fail for some intermittent reason. The default value is 2.


networkTimeout: number

Timeout for all network requests in milliseconds. If set to Infinity, then there is no network timeout. The default value is 10000.


owner: Owner

The owner object used to update jigs and approve transactions. See the Owner API. You may change the owner anytime.


purse: Purse

The purse used to pay for transactions. You may change the purse anytime.


state: State

State providr used by Run to load jigs efficiently. You may change the state provider anytime.


timeout: number

Timeout for all Run actions in milliseconds. This applies to load(), sync(), import() and the inventory's sync(). If set to Infinity, then there is no timeout. The default value is 10000.

static Jig

Create a custom jig that extends the Jig base class

class MyObject extends Run.Jig {
  // ...

static Jig: Jig

Jig class that is common for all Run instances. It is set as Jig at the global scope. You must extend from this base class to create a jig. See Jig.

static Code

static Code: Code

Code base class that all deployed classes or functions inherit from. See Code.

static Berry

static Berry: Berry

Berry base class that defines a method for loading third-party data and its structure. See Berry.

static Creation

static Creation: Creation

Creation base class that jigs, code, and berries all share. See Creation.

static Transaction

static Transaction: Transaction

Transaction class used to manually create, update, and inspect Run transactions. See Transaction.

static plugins

static plugins: object

Contains the plugins that ship with the Run SDK and may be used to configure Run. See Plugins

static extra

static extra: object

Contains the standard library of code jigs that ship with the Run SDK. See Extras.

static api

static api: object

An object that contains all plugin APIs that a user may implement. See APIs.

static util

static util: object

Various utility functions and classes. See Util

static configure(env, network)

Configure Run from the command line


static configure(env: object, network: ?string)

Configures Run's defaults with the provided environment object. This is typically process.env. This provides an easy way for apps to setup Run from the shell. When Run is instantiated, it will use these settings as defaults.

The network parameter is optional. If specified, it overrides the value in the environment variables. Run will pick the PURSE and OWNER keys for that specific network.

Environment variables

Name Description Possible Values Default
APP App identifier used in Run transactions your app string ''
LOGGER Whether to log internal messages to the console true, false, debug false
NETWORK Network string mock, main, test, stn mock
PURSE Purse key used your string privkey undefined
PURSE_[network] Purse key used on a specific network your string privkey undefined
OWNER Owner key used your string privkey undefined
OWNER_[network] Owner key used on a specific network your string privkey undefined
API Blockchain API when using mainnet or testnet run, whatsonchain run
APIKEY API key for the blockchain API your string api key undefined
APIKEY_[api] API key used with a specific API your string api key undefined

static protocol

static version: number

The version number of the RUN protocol. Jigs that you deploy will be tied to a particular protocol. Jigs and other creations deployed using protocol v5 and above and guaranteed to be supported in the future.

static version

static version: string

Semantic version of the Run SDK.

static instance

static instance: Run

The active Run instance. All jig instantiations, updates, and class deployments will occur on the active run instance. The owner of that instance will sign transactions and its blockchain and purse are the ones which will be used. You should not create more than one Run instance in your application, but you may use this variable to access that instance.


class Jig extends Creation { ... }

Base class for objects and code that can be owned on the blockchain and updated by calling methods. Jigs have various internal rules that ensure they are able to be safely composed together and called from each other. All classes that extend from Jig are themselves jigs as well as Code. Jigs are also Creations and have location, origin, and nonce properties.


Simple jig that takes two parameters in its constructor

class SimpleStore extends Jig {
  init(a, b) {
    this.a = a
    this.b = b
const store = new SimpleStore(1, 2)
console.log(store.b) // prints 2


The initialization method for jig objects. init() is to jigs as constructor() is to normal classes. Run will call init automatically when the class is instantiated, just like constructors, and init() cannot be called directly by users. You may pass parameters into init() and also call super.init() to call its parent initializer.


sync(options: ?object): Promise<Jig>

Synchronizes the jig object with the blockchain. If there are any pending transactions for this jig to publish, this method will wait for them to broadcast. If there are no pending transactions, then this method will update the jig and any internally-referenced jigs to their latest states on the blockchain.

This method supports two options: forward and inner. If you pass { forward: false }, then only pending transactions will be published and new updates will not be downloaded. This may be useful for performance reasons or if the Blockchain API does not support forward syncing, as is the case with WhatsOnChain. If you pass { inner: false }, then only the current jig will be updated and any internally-referenced creations will not be explicitly updated.


Property Description Default
forward Whether to sync the jig forward to its latest on-chain state undefined
inner Whether to also sync any referenced creations undefined


destroy(): Jig

Destroys the jig. The destroyed jig will acquire a final location that ends with _dN, where N is the index of the destroyed jig in its final transaction. This location is uniquely identifiable and the jig may still be referenced. However, it can no longer be updated. You may override the destroy() method to perform custom destroy behavior.


auth(): Jig

Proves ownership over the current jig by spending its output in a transaction. You may override the auth() method.

static load(location)

Load a jig

const msg = await Message.load('4e146ac161324ef0b388798462867c29ad681ef4624ea4e3f7c775561af3ddd0_o1')

static load(location: string): Promise<Berry>

Loads a jig object that is an instance of the particular jig class. This is an alternative to run.load() for when you know the type of jig to load. This method is accessible when loading berries unlike run.load().


class Code extends Creation { ... }

Code is the base class for classes and functions deployed on-chain. Unlike Jig however, you do not need to extend from Code yourself. When you call run.deploy on a class or function, the returned sandboxed code is a Code instance that gets all the functions and properties below. This lets you to upgrade, send and destroy code just like object jigs! All code are also Creations and have location, origin, and nonce properties.

There are two kinds of Code: jig code and sidekick code. Jig code are classes that extend from Jig and behave just like jig objects, meaning their methods are protected and static function calls can update their state. Sidekick code are functions or classes that do not extend from Jig, and cannot be updated in that way over time. Sidekick code has no special rules unlike jigs and so is better suited for helper code. The Code base class is available via Run.Code. Both jig code and sidekick code however may be upgraded, destroyed, and signed.


sync(options: ?object): Promise<Code>

Synchronizes code with the blockchain. If there are any pending transactions to publish, this method will wait for them to broadcast. If there are no pending transactions, then this method will update the code and any internally-referenced creations to their latest states on the blockchain.

This method supports two options: forward and inner. If you pass { forward: false }, then only pending transactions will be published and new updates will not be downloaded. This may be useful for performance reasons or if the Blockchain API does not support forward syncing, as is the case with WhatsOnChain. If you pass { inner: false }, then only the current jig will be updated and any internally-referenced creations will not be explicitily updated.


Property Description Default
forward Whether to sync the code forward to its latest on-chain state undefined
inner Whether to also sync any referenced creations undefined


Destroy a token class during deploy to stop future mints

class GiftCard extends Token { }

run.transaction(() => {

destroy(): Code

Destroys the code so that it cannot be updated in the future. The destroyed code will acquire a final location that ends with _dN, where N is the index of the destroyed code in its final transaction. This location is uniquely identifiable and the code may still be referenced and instantiated. However, it may no longer be updated.


Enforce that only the owner of a jig class may create instances

class Coin extends Jig {
  init() {

auth(): Code

Proves ownership over the current code by spending its output in a transaction.


Upgrade a jig class to add a new method

const DragonCode = await run.load(classLocation)

class Dragon extends Jig {
  setName(name) { = name }
  setAge(age) { this.age = age }


await DragonCode.sync()

upgrade(T: function)

Replaces the code with new behavior. With great power comes great responsibility. This method can completely change the behavior not just of the class but of any instances. It is best to use this feature to make bug fixes but not major changes. Once you are confident in the security of the code, you can set the upgradable property to false to prevent further upgrades. Jig objects, as instances of jig code, will be automatically upgraded to the new behavior when they call sync() and their class reference gets upgraded.


static deps: ?object

The dependencies of this code. These must be manually specified in order for Run to load them into the code sandbox. And properties on deps are added as globals within the sandbox.


interactive: boolean

Whether the code is allowed to openly interact with any other code. The default value is true. However, you may wish to set this value to false if you only want your class and its jigs to interact with itself and any of its code references. You can use this create a code family where only code, and jigs created from that code, in the group are allowed to interact together.


sealed: true | false | 'owner'

The sealed property defines the rules for how a class can be extended. If true, then no extensions are allowed. If false, then anyone may extend from the class. If 'owner', then the class's owner must authorize of any extensions to the class. The default value is 'owner' so that a class hierarchy can be trusted and the instanceof keyword is safe by default.


upgradable: boolean

Whether the code is allowed to be upgraded. You may wish to set this value to false to prove that the behavior will not change. The default value is true.


Define a berry class

class TwetchPost extends Berry {
    init(text) {
        this.text = text

    static async pluck(location, fetch) {
      const data = txo(await fetch(location))
      if (data.out[0].s2 === '19HxigV4QyBv3tHpQVcUEQyq1pzZVdoAut') { // B protocol
        return new TwetchPost(data.out[0].s3)

TwetchPost.deps = { txo }

class Berry extends Creation { ... }

Berry is a base class for defining how data from third-party protocols should be loaded. Each class that extends from Berry defines a type of data. Berry instances, or simply berries, are read-only objects that represent this parsed data. Once loaded, but they may be used within jigs. All berries are also Creations and have location, origin, and nonce properties.



The initialization method for berry instances. You may pass parameters into init() and use those parameters to setup the berry. The pluck() method must create a new instance of the berry which will call init().

static pluck(path, fetch)

pluck(path: string, fetch: function): Promise<Berry>

Plucks a berry from the blockchain. You will override this method to load a berry instance. The berry class should fetch the transaction using async fetch(). This will return a raw transaction in hex format. The Berry should parse the transaction, perhaps using Tx or txo, and then instantiate a new Berry of the appropriate type with the data parsed out. If additional berries are required to build this one, they may be plucked recursively using Berry.load().

static load(path)

Load a berry

const post = await TwetchPost.load('4e146ac161324ef0b388798462867c29ad681ef4624ea4e3f7c775561af3ddd0')

static load(path: string): Promise<Berry>

Loads a berry of a particular type. Run internally calls the berry class's pluck() method to load the berry. load() may be also called recursively inside of Berry.pluck() to load sub-berries. You cannot override load().


Check that objects are indeed creations

Token2 instanceof Creation
// true

new Dragon() instanceof Creation
// true

twetchPostBerry instanceof Creation
// true

class Creation { ... }

A JavaScript object that Run can be loaded from the blockchain. This includes jigs, code, and berries. The Creation class, available via Run.Creation is the effective base class for all creations. All creations have the location bindings location, origin, and nonce as well as UTXO bindings owner and satoshis. They can be passed into jig functions and referenced as properties. To load a creation, call run.load with its corresponding location.


Two different tickets have different origins

class Ticket extends Jig { }
const ticket1 = new Ticket()
const ticket2 = new Ticket()
await run.inventory.sync()
// ticket1.origin !== ticket2.origin

origin: string

The unique blockchain location where the creation was initially deployed or loaded that distinguishes it from all other creations. The format for origin is generally TXID_oN where TXID is the bitcoin transaction ID where the creation was first deployed. o is shorthand for output and N is the zero-based index representing this creation. Deleted creations, instead of ending in _oN, end in _dN instead. Berries have additional query parameters in their origin. In any case, the origin is set automatically by Run after deploying or loading the creation and it becomes read-only thereafter. Jig methods may internally read the origin anytime after it is initially published.


The value of location changes with every update

class Weapon extends Jig {
  upgrade() {
    this.upgraded = true

const weapon = new Weapon()
await weapon.sync()
// weapon.origin === weapon.location

await weapon.sync()
// weapon.origin !== weapon.location

location: string

The blockchain location that uniquely identifies the current state of the creation. This is in the same form as origin. However, unlike origin, location will update with every state change on the creation. When there is a pending change, reading location will throw an error. This is because the Bitcoin transaction ID is not yet known so its location is undetermined. To avoid this error, be sure to call sync before reading the location. Finally, note that location, like origin, is a read-only property that Run updates for you.


nonce: number

The number of transactions this creation was updated in. This may be used to determine if one creation state is newer than another. Like origin and location, this is a read-only property that Run updates for you.


Transferring ownership of a code jig

class FrequentFlyerRewards extends Jig {
  static transfer(to) {
    this.owner = to


owner: string|Lock

The owner is either a Bitcoin address string, a public key in hex, or a custom Lock that creates an output script. A jig may change this property to change owners, but it is read-only from outside the creation.


Backing a jig with Bitcoin

class Item extends Jig {
  init() {
    this.satoshis = 10000

satoshis: number

This number represents the amount of Bitcoin in satoshis that are backing this creation. It may be increased or decreased but it may not be set below zero. Increasing this value will deposit Bitcoin into the output for the jig from the Run purse. Decreasing it will withdraw Bitcoin to the Run purse.


class Store extends Jig {
  set(value) { this.value = value }

const store = new Store()

const tx = new Run.Transaction()

tx.update(() => {
  store.set('Hello, world')

await tx.publish()

class Transaction { ... }

The Transaction class gives you to finer control over the current Bitcoin transaction being built by Run. This class is available via Run.Transaction. It allows you to:

Normally, when you update a jig that you own, Run will begin a transaction for you automatically. However, you can take control of this process by creating a new Transaction and calling update() on the transaction to perform the update yourself. When you are finished, you can call publish() to broadcast the transaction to the blockchain or export() to save the transaction locally. Alternatively, you may cancel the updates by calling rollback. Other parties may load your exported transaction by calling run.import and then inspecting its contents using outputs and deletes arrays. If they approve of the updates to their jigs, they may call sign and then publish to broadcast the transaction.


Deploy multiple jig classes in a single transaction

const tx = new Run.Transaction()
tx.update(() => run.deploy(Picasso))
tx.update(() => run.deploy(Monet))
tx.update(() => run.deploy(VanGogh))
await tx.publish()

update(callback: function)

Adds additional updates to the transaction. This may include calling a jig method, deploying code, upgrading code, destroying jigs, and more. The callback function passed in will be called to record the new changes.


publish(options: ?object): Promise<string>

Finalizes the transaction and publishes it to the blockchain. Returns the txid as a hex string.


Property Description Default
pay Whether to pay for the transaction true
sign Whether to sign the transaction true


export(options: ?object): Promise<string>

Exports the in-progress transaction as a raw hex string. This transaction may be imported or broadcast afterward.


Property Description Default
pay Whether to pay for the transaction true
sign Whether to sign the transaction true


Import and cache a transaction from the blockchain

const tx = await run.import(rawtx, { txid })

await tx.cache()

cache(): Promise<void>

Caches the jig and code states for the current transaction in the Cache. After calling cache(), the transaction is locked and there may be no more changes. This method may be useful for indexing transactions from the blockchain, or caching the state of jigs that will be broadcast by a third-party.


pay(): Promise<void>

Pays for the current transaction. This is performed automatically when publish() or export() is called, but you may wish to call it manually if you are paying with multiple purses or co-signing the transaction with others. If any additional updates are made to the transaction, including calling jig methods or deploying new code, then the transaction must be paid for again.


sign(): Promise<void>

Signs all inputs involved in the current transaction using the active Run owner. The transaction should only be signed after all updates are added and the transaction has been paid for via pay(). After all required signatures are added, then the transaction may be broadcasted, and if the transaction requires signatures from multiple different owners, then it must be exported and imported by other parties to be signed. If any additional updates are made to the transaction, including calling jig methods or deploying new code, then the signatures are reset and the transaction must be paid for again and re-signed by all parties.


class Store extends Jig {
  set(value) { this.value = value }

const store = new Store()

const tx = new Run.Transaction()

tx.update(() => {
  store.set('Hello, world')


// store.value is undefined again


Abandons the current transaction and reverts all changes to jigs and code. Any classes to be deployed will have their origins and locations cleared, and any jigs to be updated will revert to their prior state. Any jigs that are deployed for their first time will be reverted to an invalid state where they may no longer be used.


outputs: Array<Creation>

Jigs or code outputted from the transaction in their end state.


deletes: Array<Creation>

Jigs or code deleted within the transaction in their end state.


base: string

The starting Bitcoin transaction before any RUN inputs or outputs are added, stored as a hex string. This may be used to set a custom nLockTime or to add custom outputs before the RUN metadata. This is the only supported way to add custom outputs to a transaction before the RUN metadata. Custom inputs however are not yet supported. By default, the base property stores an empty transaction.


This section describes various classes that ship with the Run SDK that may be used to manually configure Run. Each plugin is available under Run.plugins.


Create a BrowserCache with a higher in-memory cache size

const { BrowserCache } = Run.plugins

const cache = new BrowserCache({ maxMemorySizeMB: 100 })

const run = new Run({ cache })

class BrowserCache implements Cache { ... }

A multi-level Cache implementation designed for web browsers that persists values across sessions.

BrowserCache is the default implementation of the Cache API setup by Run when using browsers. BrowserCache is a wrapper around the LocalCache and an IndexedDB store. It uses the LocalCache to quickly store and access values from local memory and the IndexedDb store to persist values across browser sessions. When a value is written, it is written both to the LocalCache and to the IndexedDB store.

BrowserCache may be accessed via Run.plugins.BrowserCache.


constructor(options: ?object)

Creates the browser cache. The options object may be used to configure the cache.

Property Type Description Default
maxMemorySizeMB number Max size in megabytes (MB) of the cached data stored in memory 10 (10MB)
dbName string Database name 'run-browser-cache'
dbVersion number Database version 1
dbStore string Object storage name 'run-objects'


maxMemorySizeMB: number

Size in megabytes (MB) of the in-memory cache. This value may be changed at runtime.


Tracks jigs assigned to the current owner. An Inventory is automatically created with a new Run instance and assigned to Run.inventory.


Load all jigs that are tickets

// Update the inventory's jigs
await run.inventory.sync()

// Find the ticket
const ticketClassOrigin = 'e4a9618d3a187448feeb95ff30f7ec6381a025316cdcae2cdf388ad3de7fab6f_o1'
const ticket = run.inventory.jigs.find(jig.constructor.origin === ticketClassOrigin)

jigs: Array<Jig>

Returns an array of all jig objects owned by the Run owner. This array is cached. To update it, call run.inventory.sync().


Load the user's classes

// Update the inventory's code
await run.inventory.sync()

// Find all classes we known that extend from a known origin
const itemBaseClassOrigin = 'e4a9618d3a187448feeb95ff30f7ec6381a025316cdcae2cdf388ad3de7fab6f_o2'
const ItemBase = await run.load(itemBaseClassOrigin)
const itemClasses = run.inventory.code.find(T => Object.getPrototypeOf(T) === ItemBase)

code: Array<function>

An array of all jig classes and functions owned by the Run owner. This array is cached. To update it, call run.inventory.sync().

It is best to identify code using origins as seen on the right. Identifying classes by their names is not secure.


sync(): Promise<void>

Updates the local jig objects and code with the latest UTXO set.


class LocalCache implements Cache { ... }

An in-memory LRU Cache implementation with a maximum size. The Run class will create one automatically if no cache is provided.

LocalCache may be accessed via Run.plugins.LocalCache.


constructor(options: ?object)

Creates the local cache. The options object may be used to configure the cache.

Property Type Description Default
maxSizeMB number Max size in megabytes (MB) of the cached data stored in memory 10 (10MB)


maxSizeMB: number

The maximum amount of data stored in the state cache in megabytes.

If this value is less than the current size, the cache will be shrunk to fit.


class LocalOwner implements Owner { ... }

The default Owner implementation that uses a local private key to sign transactions. It is able to sign both standard locks (including addresses and public key strings) as well as group locks. Jigs created will all be assigned to the same address.

LocalOwner may be accessed via Run.plugins.LocalOwner.


constructor(options: object): LocalOwner

Creates a LocalOwner with the provided configuration.

Property Type Description Default
privkey string or bsv.PrivateKey Private key used to own jigs and other resources Randomly generated
blockchain Blockchain Blockchain used to query UTXOs. If none is specified, then the inventory will not be synced. None


privkey: string

Hex private key string used to sign jig updates. This is read-only.


address: string

Address used to assign to new jigs. This is read-only.


class LocalPurse implements Purse { ... }

The Purse implementation that Run uses by default to pay for transactions using a local wallet. This is an implementation of the Purse API.

LocalPurse may be accessed via Run.plugins.LocalPurse.


constructor(options: object): LocalPurse

Creates a LocalPurse with the provided configuration.

Property Type Description Default
privkey string or bsv.PrivateKey Private key used to own jigs and other resources Required
blockchain Blockchain Blockchain used to query UTXOs Required
splits number Number of UTXO splits to reduce mempool chain issues 1
feePerKb number Transaction fee in satoshis per kilobyte 500


privkey: string

Private key used to sign the transaction.


address: string

Address used to find UTXOs and receive payments.


Change the number of purse UTXO splits

run.purse.splits = 100

splits: number

The minimum number of UTXOs that the purse must have. If the number of UTXOs is less than this value, then Run will automatically split your UTXOs the next time a Run transaction is generated. The default value for splits is 1.

Increasing this value may avoid the too-long-mempool-chain error. For more information, see Debugging Tips.


Querying the current balance

console.log('Satoshis', await run.purse.balance())

balance(): Promise<number>

Returns a promise that resolves to the current balance in satoshis of this purse. This is the sum of all satoshis in this purse's unspent outputs.


Building a transaction using the purse

const utxos = await run.purse.utxos()
const tx = new bsv.Transaction().from(utxos).change(run.purse.address).sign(run.purse.privateKey)

utxos(): Promise<{txid: string, vout: number, script: bsv.Script, satoshis: number}>

Returns a promise that resolves to the current UTXOs of this purse.


Use LocalState rather than the default StateServer

run.state = new Run.plugins.LocalState()

class LocalState implements State { ... }

A State implementation that uses a local cache to store and retrieve jig tates. This is the default implementation on mockchain.

LocalState may be accessed via Run.plugins.LocalState.


constructor(cache: ?Cache): LocalState

Creates a LocalState with the provided configuration.


Getting the mockchain from a run instance

const run = new Run({ network: 'mock' })

const mockchain = run.blockchain

Creating a mockchain manually and passing it into Run

const mockchain = new Run.plugins.Mockchain()

const run = new Run({ blockchain: mockchain })

class Mockchain implements Blockchain { ... }

The mockchain is a local simulation of a blockchain that stored entirely in memory. It implements the Blockchain API. It accepts and validates real Bitcoin transactions using testnet settings. The mockchain simulates many aspects of a real Bitcoin API, including the 25 chained mempool limit, but everything happens locally.

We recommend using the mockchain during development and unit testing. The mockchain lets you simulate Run without requiring network connectivity and without spending real bitcoins. Note that when the program closes however, all mockchain data is lost, so it is not a substitute for a real network.

The class is accessible via Run.plugins.Mockchain, or as an instance in run.blockchain after setting the network to mock.



Creates a new mockchain. There are no parameters.

fund(address, satoshis)

fund(address: string, satoshis: number)

Directly funds an address with an amount of satoshis without requiring the spending of any inputs. The Run class will automatically fund the purse, but you may fund additional addresses using this method.



Creates a new simulated block. This is useful when the 25 chained mempool limit is hit.


Create a NodeCache in a custom direcotry

const { BrowserCache } = Run.plugins

const cache = new NodeCache({ dir: '.data })

const run = new Run({ cache })

class NodeCache implements Cache { ... }

A multi-level Cache implementation designed for node.js that persists entries in files.

NodeCache is the default implementation of the Cache API setup by Run when using node.js. NodeCache is a wrapper around the LocalCache and an file system store. It uses the LocalCache to quickly store and access values from local memory and the file system store to persist values across browser sessions in the .runcache directory. When a value is written, it is written both to the LocalCache and to the file system.

NodeCache may be accessed via Run.plugins.NodeCache.


constructor(options: ?object)

Creates the browser cache. The options object may be used to configure the cache.

Property Type Description Default
maxMemorySizeMB number Max size in megabytes (MB) of the cached data stored in memory 10 (10MB)
dir string Filesystem directory '.runcache'


maxMemorySizeMB: number

Size in megabytes (MB) of the in-memory cache. This value may be changed at runtime.


Instantiate Run and use the testnet pay server

const apiKey = '<your-api-key>'
const payServer = new Run.plugins.PayServer(apiKey)
const run = new Run({ network: 'test', purse: payServer })

class PayServer implements Purse { ... }

A Purse implementation that uses the Run Pay Server to pay for transactions.

PayServer may be accessed via Run.plugins.PayServer.


constructor(apiKey: string)

Creates the PayServer with a given API key. The API key may be generated via Only testnet is supported today.


Use to Run Connect Blockchain API

const blockchain = new Run.plugins.RunConnect()

const run = new Run({ blockchain })

class RunConnect implements Blockchain { ... }

A Blockchain implementation that connects to the Run Connect Blockchain Server.

RunConnect may be accessed via Run.plugins.RunConnect.


constructor(options: object): RunConnect

Creates a RunConnect instance with the provided configuration.

Property Type Description Default
network string Either main or test main


Use RunDB as a state provider

const state = new Run.plugins.RunDB('http://localhost:8000')

const run = new Run({ state, client: true })

class RunDB implements State { ... }

A State implementation that uses a local database of precalculated states. Usually Run client mode should also be enabled when using the RunDB plugin.

RunDB may be accessed via Run.plugins.RunDB.


constructor(host: string): RunDB

Creates a RunDB at the provided URL.


Use to Run Connect State API

const state = new Run.plugins.StateServer()

const run = new Run({ state })

class RunConnect implements State { ... }

A State implementation that connects to the Run Connect State Server.

StateServer may be accessed via Run.plugins.StateServer.


constructor(options: object): RunConnect

Creates a RunConnect instance with the provided configuration.

Property Type Description Default
network string Either main or test main


Load the jigs owned by another user

const viewer = new Run.plugins.Viewer(customLock)

const run = new Run({ owner: viewer })

await run.inventory.sync()

// run.inventory.jigs will contain their jigs

class Viewer implements Owner

An Owner implementation for loading another user's jigs.

These resources will be read-only and the Viewer will not be able to sign for any updates.

Viewer may be accessed via Run.plugins.Viewer.


constructor(owner: string|Lock)

Creates a new viewer.


Connect to WhatsOnChain API on testnet

const blockchain = new Run.plugins.WhatsOnChain({ network: 'test' })

const run = new Run({ blockchain })

class WhatsOnChain implements Blockchain { ... }

A Blockchain implementation that connects to the WhatsOnChain API.

WhatsOnChain may be accessed via Run.plugins.WhatsOnChain.


constructor(options: object): WhatsOnChain

Creates a WhatsOnChain with the provided configuration.

Property Type Description Default
network string Either main or test main


The Run SDK ships with several built-in Code creations that are part of its standard library. These include the standard Token2 class for numerical tokens and several other helpers. Each Code below is predeployed and available under Run.extra.


Create a custom R-puzzle output script


function asm(s: string): string

Converts a Bitcoin script string in ASM notation into its hex string format. This code is deterministic and safe to use within Jigs. It is often useful when creating custom owner locks.

It is available via Run.extra.asm and predeployed at the following locations:

Network Location
main 61e1265acb3d93f1bf24a593d70b2a6b1c650ec1df90ddece8d6954ae3cdd915_o1
test 1f0abf8d94477b1cb57629d861376616f6e1d7b78aba23a19da3e6169caf489e_o1


class B extends Berry { ... }

The B class loads file data stored on the blockchain into a JavaScript object. You may use B to load images, 3D models, CSS styles, and more, to attach to your jigs, to display in your apps, or for any other purpose. The B:// data format is well-established as a method for storing files on-chain, and services like Blockpress Upload allow you to upload data easily. Run uses B data to represent images for jigs. See Standard Metadata for more.

To load a B berry, call either B.load() or B.loadWithMetadata(). B will load the first output containing B data in the transaction.

It is available via Run.extra.B and predeployed at the following locations:

Network Location
main 6fe169894d313b44bd54154f88e1f78634c7f5a23863d1713342526b86a39b8b_o1
test 5435ae2760dc35f4329501c61c42e24f6a744861c22f8e0f04735637c20ce987_o1


Load B:// data into an img element

B.load('2f3492ef5401d887a93ca09820dff952f355431cea306841a70d163e32b2acad').then(b => {
  imgElement.src = `data:${b.mediaType};base64, ${b.base64Data}`

load(txid: string): Promise<B>

Loads B:// data from the transaction with the ID passed.


Load B:// data with attribution metadata

const metadata = {
  title: 'T Rex skull icon',
  license: '[CC BY 3.0](',
  author: '[Delapouite](',
  source: '[]('

await B.loadWithMetadata('55e2c09672355e009e4727c2365fb61d12c69add91215ee3e9f50aa76c808536', metadata)

loadWithMetadata(txid: string, metadata: ?object): Promise<B>

Loads B:// data and then attaches the provided metadata to the berry.

This is useful for adding attribution information to data that lacks it. See the Standard Metadata for information on metadata fields.


base64Data: string

The data stored using B:// represented in base 64.


filename: string

The filename as declared by the B:// protocol data.


mediaType: string

The W3 registered media type. Examples include image/svg+xml and image/png.


class Base58 { ... }

It is available via Run.extra.Base58 and predeployed at the following locations:

Network Location
main 81bcef29b0e4ed745f3422c0b764a33c76d0368af2d2e7dd139db8e00ee3d8a6_o1
test 424abf066be56b9dd5203ed81cf1f536375351d29726d664507fdc30eb589988_o1


decode(s: string): Array<number>

Decodes a Base58Check string into an array of bytes. This may be used to parse the public key hash data out of an address within a custom lock.


class Post extends Jig {
  init(message) {

    this.message = message

Post.deps = { expect: Run.extra.expect }

function expect(subject) { ... }

The expect function is arbitrary code to help you check with parameters in Jigs. It is similar to Jest or Chai assertions. expect takes a single argument, subject, and then lets you execute one of its assertion methods on ithe subject. If the assertion passes, then nothing happens, but if it fails, an Error is thrown.

Each method takes an optional last parameter message that is the error message to throw. If none is specified, then a default error message will be created.

It is available via Run.extra.expect and predeployed at the following locations:

Network Location
main 71fba386341b932380ec5bfedc3a40bce43d4974decdc94c419a94a8ce5dfc23_o1
test f97d4ac2a3d6f5ed09fad4a4f341619dc5a3773d9844ff95c99c5d4f8388de2f_o1




The not property reverses the condition of any methods that follow.


expect(power > 9999).toBe(true)

toBe(value: any, message: ?string)

Checks that the subject is equal to the value, using the javascript === operator. This does not, however, deeply compare values of an object, so for deep object comparison we recommend toEqual.


expect(names).toBe(['Stevie', 'Wonder'])

toEqual(value: any, message: ?string)

Deeply compares the subject to a value, which involves recursively traversing through every sub-property of objects to compare whether they are the same primitive values.



toBeInstanceOf(Class: Class, message: ?string)

Checks that an object is an instance of a class or one of its parents.



toBeDefined(message: ?string)

Checks that a value is not undefined.



toBeNull(message: ?string)

Checks that a value is null. Often this is paired with not to check that a value is not null, as seen on the right.



toBeNumber(message: ?string)

Checks that a value is a numerical type. Numbers including all integers, floating point numbers, NaN, and Infinity.



toBeInteger(message: ?string)

Checks that a value is an integer number and does not have a decimal point.



toBeLessThan(value: number, message: ?string)

Checks that a value is a number less than a particular number.


toBeLessThanOrEqualTo(value: number, message: ?string)

Checks that a value is a number less than or equal to a particular number.



toBeGreaterThan(value: number, message: ?string)

Checks that a value is a number greater than a particular number.


toBeGreaterThanOrEqualTo(value: number, message: ?string)

Checks that a value is a number greater than or equal to a particular number.



toBeBoolean(message: ?string)

Checks that a value is either true or false.



toBeString(message: ?string)

Checks that a value is a string. It may still be the empty string however.



toBeObject(message: ?string)

Checks that a value is a non-null object or an Array.



toBeArray(message: ?string)

Checks that a value is an array. It may be empty.



toBeSet(message: ?string)

Checks that a value is a Set instance. It may be empty.



toBeMap(message: ?string)

Checks that a value is Map instance. It may be empty.



toBeUint8Array(message: ?string)

Checks that a value is a Uint8Array instance. It may be empty.



toBeClass(message: ?string)

Checks that a type is a class.



toBeFunction(message: ?string)

Checks that a type is a function. Classes are not considered functions for this assert.



toBeJigClass(message: ?string)

Checks that a type is a class that extends from Jig.



toExtendFrom(T: function)

Checks that a class extends from another class.


Create and then sign a 2-3 multi-sig

// Create a token owned by a 2-3 multi-sig
token.send(new Group([pubkey1, pubkey2, pubkey3], 2))

// Begin a transaction to spend it and sign with key #1
const run = new Run({ owner: privkey1 })
const tx = new Run.Transaction()
tx.update(() => token.send(address, 100))
await tx.sign()

// Co-sign with key #2
run.owner = privkey2
await tx.sign()
await tx.publish()

class Group implements Lock { ... }

A group lock is a m-of-n multi-sig output used to have more than one user own a resource. Combined with the LocalOwner and TransactionAPI, Run is able to sign group locks using its default LocalOwner in any order. See the example to the right.

A Group lock is as secure as bitcoins themselves. If some parties can update a jig, they can also destroy the jig.

It is available via Run.extra.Group and predeployed at the following locations:

Network Location
main 780ab8919cb89323707338070323c24ce42cdec2f57d749bd7aceef6635e7a4d_o1
test 63e0e1268d8ab021d1c578afb8eaa0828ccbba431ffffd9309d04b78ebeb6e56_o1

constructor(pubkeys, required)

constructor(pubkeys: Array<string>, required: number): Group

Creates a m-of-n Group for the set of public keys.

The maximum length of pubkeys is 16. If required is not specified, then it is the number of pubkeys.


add(pubkey: string)

Adds a pubkey to the pubkey list if it does not already exist.

pubkeys: Array

Array of public keys that are partial owners. There can be no more than 16 and they must be hex strings.

required: number

Number of signatures required to unlock the output. This is the m in m-of-n multi-sig.


It is available via Run.extra.Hex and predeployed at the following locations:

Network Location
main 727e7b423b7ee40c0b5be87fba7fa5673ea2d20a74259040a7295d9c32a90011_o1
test 1f0abf8d94477b1cb57629d861376616f6e1d7b78aba23a19da3e6169caf489e_o2

static stringToBytes

static bytesToString(b: Array<number>): string

Converts a array of bytes to a hex string. This method will throw if any entries in the array are not bytes.

static stringToBytes(s: string): Array<number>

Converts a hex string into an array of bytes. This method will throw if the string is not a a valid hex string.


function sha256(data: Array<number>): Array<number>

Performs a SHA256 hash on arbitrary data. This may be used within jigs or custom locks.

It is available via Run.extra.sha256 and predeployed at the following locations:

Network Location
main 3b7ef411185bbe3d01caeadbe6f115b0103a546c4ef0ac7474aa6fbb71aff208_o1
test 4a1929527605577a6b30710e6001b9379400421d8089d34bb0404dd558529417_o1


class Token extends Jig { ... }

Token is a standard base class for fungible tokens similar to ERC-20 or SLP. It may be used for shares, loyalty points, gift cards, and more. Each Token instance defines a numerical amount held by its owner. You extend from Token to define a new kind of token. As the owner of this new token class, only you can mint new token instances. The token instances you mint though may be sent, owned, traded, and combined together with others. Like bitcoins, they are permissionless and only require their owner's approval to use.

Token supports integer amounts like ERC-20 in its amount field. In practice, you will often wish to display the token's amount with a decimal, like 1.50. The static decimals property may be used to declare how many digits the amount is to be shifted when the amount is displayed. In the previous example, amount would be 150 and decimals would be 2.

It is available via Run.extra.Token and predeployed at the following locations:

Network Location
main 72a61eb990ffdb6b38e5f955e194fed5ff6b014f75ac6823539ce5613aea0be8_o1
test 7d14c868fe39439edffe6982b669e7b4d3eb2729eee7c262ec2494ee3e310e99_o1

static mint(amount, to)

Minting a new token

class MyCustomToken extends Token { }

const token =

mint(amount: number, to: ?(string|Lock)): Token

mint() issues a new token with a specified amount. Only the owner of the extended token class is able to call this method. The newly minted token will be assigned to the to address if specified, or to to the token class's owner if not.

send(to, amount)

const token = new MyCustomToken(100)

const sent = token.send(pubkey, 20)

console.log(sent.amount) // 20
console.log(token.amount) // 80

send(to: string|Lock, amount: ?number): Token

Sends amounts from this token to another user, creating a new Token in the process. The returned token will have the amount specified and the current token will have its amount decreased accordingly. When its amount becomes zero, the token is automatically destroyed. If amount is not specified, when the entire token amount is sent.


Combining three tokens newly minted

const token1 = new MyCustomToken(10)
const token2 = new MyCustomToken(20)
const token3 = new MyCustomToken(30)

const combined = token1.combine(token2, token3)

console.log(combine.amount) // 60

Combining and sending tokens in a single transaction

const tokens = run.inventory.jigs.filter(jig => jig instanceof MyCustomToken)

run.transaction(() => {
  const combined = tokens[0].combine(...tokens.slice(1))

  combined.send(pubkey, amount)

combine(...tokens: Token): Token

combine will merge the multiple tokens into a single token that has the combined amount. The tokens to combine must all be the same kind and the returned token object will be the same token that was called.

Tokens are like Bitcoin outputs. Every time you send some tokens, you split off an amount into a new output. Just like Bitcoins, you may later want to merge them back together. It is often useful to do this right before sending your tokens so that you can send their full amount. The example on the right shows how to combine and send tokens in a single transaction.


amount: number

The integer value held within this token. The meaning of amount depends on the token.

static decimals

class USDToken extends Token { }

USDToken.decimals = 2

const dollars = new USDToken(100)

let displayAmount = dollars.amount
while (let i = 0; i < USDToken.decimals. i++) {
  displayAmount /= 10
console.log(displayAmount) // 1.00

static decimals: number

The number of decimal places to shift the amount when displaying it. Token uses integers by default for precision, just like ERC-20, but often times you will want to specify a decimals value to indicate a unit for display to the user. For example, a US Dollar coin might set decimals to 2 so that the base amount is cents but the display value is dollars.


Load an OP_RETURN into a berry

class OpReturn extends Berry {
  static async pluck(txid, fetch) {
    const rawtx = await fetch(txid)
    const tx = new Tx(rawtx)
    const script = tx.outputs[0].script
    if (!script.startsWith('6a')) throw new Error('No an OP_RETURN')
    return new OpReturn(tx.outputs[0].script)

  init(script) { this.script = script }

OpReturn.deps = { Tx: Run.extra.Tx }

class Tx { ... }

Parses a raw hex transactions into an object that can be inspected. This is often useful when creating berries from transactions.

It is available via Run.extra.Tx and predeployed at the following locations:

Network Location
main 312985bd960ae4c59856b3089b04017ede66506ea181333eec7c9bb88b11c490_o2
test 33e78fa7c43b6d7a60c271d783295fa180b7e9fce07d41ff1b52686936b3e6ae_o2


constructor(rawtx: string): Tx

Parses the raw transaction into a Tx object. The constructor will throw an error if rawtx is not a valid Bitcoin transaction.


inputs: Array<{prevTxId: string, outputIndex: number, script: string, sequenceNumber: number}>

Transaction inputs array.


outputs: Array<{satoshis: number, script: string}

Transaction outputs array.


version: number

The version number of the transaction.


nLockTime: number

The lock time of the transaction.


Parse a Twetch transaction into a berry

const { txo } = Run.extra

class TwetchPost extends Berry {
  init (text) {
    this.text = text

  static async pluck (txid, fetch) {
    const data = txo(await fetch(txid))
    if (data.out[0].s2 === '19HxigV4QyBv3tHpQVcUEQyq1pzZVdoAut') {
      return new TwetchPost(data.out[0].s3)

TwetchPost.deps = { txo }

function txo(rawtx: string): object

Parses a raw hex transaction into a TXO data structure. This is often an easy way to interpret a transaction for a Berry.

The following fields are supported:

It is available via Run.extra.txo and predeployed at the following locations:

Network Location
main 312985bd960ae4c59856b3089b04017ede66506ea181333eec7c9bb88b11c490_o1
test 33e78fa7c43b6d7a60c271d783295fa180b7e9fce07d41ff1b52686936b3e6ae_o1


Check if a custom owner implementation will be accepted by Run

class MyOwner { /* implementation */ }

console.log(new MyOwner() instanceof Run.api.Owner)

This section describes APIs that may be implemented by the developer to customize Run. Each API is available under Run.api and some commonly-used implementations of these APIs are provided via the built-in Plugins. You may check that your implementation conforms to the interface by using instanceof on instances. You do not have to extend from the API classes for an implementation to be considered valid.


class Blockchain { ... }

The interface Run uses to communicate with the Bitcoin network. The Run SDK ships with several implementations: RunConnect, WhatsOnChain, and the Mockchain. Developers may implement Blockchain to connect to the Bitcoin network in custom ways.


network: string

A friendly network string. This is usually one of main, test, stn, or mock, however it may be any string. If the network starts with 'main', the Run SDK will use mainnet settings wherever it matters. For all other networks, Run will use testnet settings.


Create and broadcast a simple transaction

const rawtx = new bsv.Transaction()
  .to(address, amount)

await run.blockchain.broadcast(rawtx)

broadcast(rawtx: string): Promise<string>

Submits a raw transaction in hex format to the network. A promise is returned that must resolve with the transaction ID if the transaction was accepted. If the network did not accept the transaction, then the promise should be rejected with the error. This method should resolve successfully for broadcasts of transactions which are already in the mempool.


Downloads a transaction from the network

const txid = 'afc557ef2970af0b5fb8bc1a70a320af425c7a45ca5d40eac78475109563c5f8'

const rawtx = await run.blockchain.fetch(txid)

const tx = new bsv.Transaction(rawtx)

fetch(txid: string): Promise<string>

Downloads a transaction from the network. A promise is returned that will resolve with the raw hex transaction or reject with the error if the transaction could not be retrieved.


Downloads the current UTXOs for a given address

const address = 'mpBU73vq9ajhkXknP1sNGe6wjXH7QtwmWm'
const script = Script.fromAddress(address).toHex()
const utxos = await run.blockchain.utxos(script)
const tx = new bsv.Transaction().from(utxos).change(address)

utxos(script: string): Promise<Array<{txid: string, vout: number, script: string, satoshis: number}>>

Returns the unspent outputs for a given address. A promise is returned that will resolve with an array of UTXOs, which may be empty, or reject with an error. Each returned UTXO may be converted to a bsv.Transaction.UnspentOutput. The output script passed into utxos will be in hex format.

Usually, implementations will index UTXOs by the script's hash rather than the script itself. The utxos method takes a full script however to support partial compatibility for certain script patterns like P2PKH that often have dedicated query APIs. To calculate a script hash from a script using the bsv library, use the following: sha256(new Script(script).toBuffer()).reverse().toString('hex').


time(txid: string): Promise<number>

Returns the block time the transaction was confirmed, or the mempool acceptance time if not yet in a block, in milliseconds since the unix epoch.

spends(txid, vout)

spends(txid: string, vout: number): Promise<?string>

Returns the ID of the transaction that spends the given output, or null if the output is unspent.

If the Blockchain API does not support spends, it may return a Run.error.NotImplementedError, however, Run will only partially work in this case.


A cache implementation that stores data in the browser's local storage

class LocalStorageCache {
  async get(key) {
    const x = localStorage.getItem(key)
    if (x) return JSON.parse(x)

  async set(key, value) {
    localStorage.setItem(key, JSON.stringify(value))

class Cache { ... }

The interface Run uses to cache jig state, transactions, and other data needed for fast use. The Cache API also enables third-party state servers to exist and provide the intermediate state of jigs. Most values stored are immutable and all are JSON-serializable. They should not be modified or created by hand.

The following keys will be set by Run:

Key Description
jig://<location> Serialized state for jigs and code
berry://<location> Serialized state for berries
tx://<txid> Raw transaction hex
time://<txid> Transaction time in milliseconds since the unix epoch
spend://<location> Transaction ID that spends the output
trust://<txid> Whether a transaction is trusted (true) or not (false)
ban://<location> Jig location that is known to be unloadable
config://<key> Configuration setting used by Run to be persisted


get(key: string): Promise<?object>

Gets the value for a particular key. If this is an LRU cache, get() should also bump the key to the front.

Run will call this when loading jigs to see if it can short-circuit its loading. If a value exists and is valid state, Run will use it. This method is asyncronous to allow for third-party network calls.

set(key, value)

set(key: string, value: object): Promise<void>

Caches a value for a particular key.

Run will call this whenever a new transaction is published and also when a jig is loaded. This method is asyncronous to allow for third-party network calls.


Send a token to a P2PK output script

const { asm } = Run.extra

class PayToPublicKeyLock {
  constructor(pubkey) { this.pubkey = pubkey }
  script() { return asm(`${this.pubkey} OP_CHECKSIG`) }
  domain() { return 74 }

PayToPublicKeyLock.deps = { asm }

token.send(new PayToPublicKeyLock(pubkey))

class Lock { ... }

Locks are custom output scripts that may be assigned as owners to jigs. Every lock is an instance of a lock class that is deployed on-chain. The lock class's script() method defines how the output script is built from the lock instance's properties. Because the lock class is also deployed on-chain, jig code can use logic that relies on strongly typed owners. For example, perhaps a jig must be held by 3 people in a Group for it to be used.


script(): string

Returns the output script for the current lock as a hex string.

Run will call this method when building your transactions. Run provides the asm utility function to more easily build these scripts. For security reasons, this function should always rebuild the script when it's invoked and never cache the results.


domain(): number

Returns the maximum size of this lock's unlocking script in bytes. Run uses this value to improve fee estimation for signatures exist by creating placeholders in unlocking scripts that are of size domain().

Calculating the domain may depend on various properties of the lock. As a rule of thumb, Bitcoin signatures are at most 74 bytes in script, and public keys when compressed are 34 bytes in script. It is best to err on the conservative side.


Write info, warn, and error messages to a file

class FileLogger {
  constructor(path) { = fs.createWriteStream(path, { flags: 'a' }) }

  info(...messages) { this.log('INFO', ...messages) }
  warn(...messages) { this.log('WARN', ...messages) }
  error(...messages) { this.log('ERROR', ...messages) }

  log(type, ...messages) {`${type} ${messages.join(' ')} \n`) }

const run = new Run({ logger: new FileLogger('log.txt') })

class Logger { ... }

A custom logger API that may be used to intercept Run logs and send them to a more appropriate place. By default, Run will log errors and warnings to the console, but you may wish to log them to a custom file, or enable the info and debug logs too. It is not necessary to implement all methods below; whichever methods are implemented, Run will call.



Called when Run is performing a major action, such as loading a jig, or querying a REST API.



Called when Run detects an error. These are recommended for production logs.



Called when Run detects a possible error. These are recommended for production logs.



Called when Run creates debug messages. These will be more far verbose than you would typically expect in production logs.


An owner that runs on a REST server

class RemoteWallet {
  constructor(host, address) { = host
    this.address = address

  async nextOwner() { return this.address }

  async sign(tx, parents, locks) {
    const options = {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: { tx, parents }

    const rawtx = await fetch('/sign', options).then(r => r.json())
    return rawtx

class Owner { ... }

An owner of jigs and other resources that is run.owner.

Run calls the Owner API to create new jigs and sign transactions for the user. It is different from the purse which is strictly for paying for transactions. This API supports both local and remote ownership via the async methods.

For a complete guide on implementing the Owner API for a third-party wallet, please reach out to @niv in the Atlantis slack.


nextOwner(): Promise<string|Lock>

The owner address, pubkey, or lock, used to assign to new jigs.

sign(rawtx, parents, locks)

Sign all resources that are P2PK outputs

async sign(rawtx, parents, locks) {
  const tx = new bsv.Transaction(rawtx)

  for (let i = 0; i < tx.inputs.length; i++) {
    if (locks[i] instanceof PayToPublicKeyLock) {
      const sig = generateSignature(tx, i, parents[i], this.privateKey)


  return tx.toString('hex')

sign(rawtx: string, parents: Array<?{satoshis: number, script: string}>, locks: Array<?Lock>): Promise<string>

Signs the transaction for the current jig owner.

The parents array is the same size as the transaction's inputs and contains a list of the parent outputs that are inputs in this transaction. This information may be needed to generate sighash values.

The third parameter, locks, are the jig owners for each jig input. This is a higher-level representation of the parent output scripts that allows the sign method to more easily determine which inputs to sign. If an input is not a jig, then its value in the array will be undefined. If the jig's owner is an address or public key, then the lock will be a CommonLock.


class Purse { ... }

An interface to pay for transactions that is the purse in Run. Run's default Purse implementation is LocalPurse

For a complete guide on implementing the Purse API for a third-party wallet, please reach out to @niv in the Atlantis slack.

pay(rawtx, parents)

Pay for a transaction using specific UTXOs

class PayWithUtxos {
    constructor(utxos, privateKey) {
        this.utxos = utxos
        this.privateKey = privateKey

    async pay(rawtx) {
        const tx = new bsv.Transaction(rawtx)
        return tx.toString('hex')

const run = new Run({ purse: new PayWithUtxos(utxos, privateKey) })

pay(rawtx: string, parents: Array<{satoshis: number, script: string}>): Promise<string>

Pays for a transaction so that it is acceptable to miners.

The transaction is passed in raw hex format. Raw transaction do not have information about their parent outputs, so the second parameter is a parents array that is a 1-1 mapping with the inputs of the transaction. This method should return a paid transaction in raw hex format.

To pay for a transaction, the method should add inputs and outputs so that its fee is raised high enough to be accepted by miners, and then the purse should sign the inputs it adds. As of May 2020, an appropriate miner fee is 0.5 satoshis per byte. The transaction passed will include placeholder signatures for any jig inputs to help with fee estimation.

This method should not assume that all inputs and outputs are dust because there may be backed jigs that were updated or created. A third-party implementation can check that there are no backed jigs by looking for any non-dust inputs or outputs. Otherwise, the purse should be prepared to pay more than the miner fee to back jigs and receive change from unbacked jigs.

pay() is an asynchronous call that returns a promise. If an error is thrown, then the state of all jigs in the transaction will be reverted and the transaction will not be broadcasted. It is up to the purse to add retry logic if needed.


broadcast(rawtx: string): Promise<>

A notification for purses when a transaction they paid for is being broadcast.

This method is optional for purses. Wallets may choose to broadcast the transaction themselves so that they know the network will receive it and may also update their UTXOs. This method is called before Run broadcasts the transaction and any errors thrown will stop the subsequent broadcast.


cancel(rawtx: string): Promise<>

A notification for purses when a transaction they paid for is no longer going to be broadcast.

This method is optional for purses. It is designed for wallets to update their UTXOs. The rawtx passed to cancel() is the one the purse returned from pay().


class State { ... }

An interface that Run uses to fetch higher-level information about jigs efficiently. Run ships with several implementations. The default State implementation is the StateServer on mainnet and testnet. However LocalState is used with the mockchain, and RunDB may be preferred for application servers.

pull(key, options)

pull(key: string, options: ?object): Promise<*>

Downloads Run state from the API.

The key is equivalent to cache keys. The options specifies hints that may be used for additional states to be returned and cached.

Option Type Description
all boolean Whether all dependent state will be needed soon
tx boolean Whether transaction data will be needed soon


locations(script: string): Promise<Array<string>>

Returns the jig locations owned by a given hex script, which may be smaller than the set of utxos.


broadcast(rawtx: string): Promise<>

A notification for state providers when a new transaction should be indexed.

This method is optional for state providers.


This section describes various helper functionality made available via Run.util.


Send a token to a P2PKH address

token.send(new CommonLock(address))

class CommonLock implements Lock { ... }

The CommonLock generates a standard P2PKH output script for an address. It is created internally and automatically by Run whenever an address or public key is set as a jig owner. CommonLock instances are also passed into the locks array in the Owner API's sign method, and they may be created and used on their own as seen on the right. CommonLock may be accessed via Run.util.CommonLock.

constructor(address, testnet)

constructor(address: string, testnet: ?boolean): CommonLock

Creates a CommonLock for a specific address.


address: string

The address string for this lock.


testnet: ?boolean

Whether this address is intended for testnet (true), mainnet (false), or an unspecified network (undefined).


Preinstall a class with presets to share it in a library

class Token extends Jig { ... }

Token.presets = {
  main: {
    location: 'b17a9af70ab0f46809f908b2e900e395ba40996000bf4f00e3b27a1e93280cf1_o1',
    origin: 'b17a9af70ab0f46809f908b2e900e395ba40996000bf4f00e3b27a1e93280cf1_o1',
    nonce: 1,
    owner: '1PytriYokKN3GpKw84L4vvrGBwUvTYzCpx',
    satoshis: 0

module.exports = Run.util.install(Token)

install (T: function): Code

Installs a class or function as Code but does not deploy it nor require a Run instance to be created. If the resulting code is synced or referenced by another creation, it will automatically be deployed in the next transaction. This method is sometimes useful for providing sandboxed code to third-parties without requiring a Run instance to be created. For example, the built-in extras that ship with Run are pre-installed code.


Print out the Run transaction metadata


  "app": "",
  "version": 5,
  "in": 0,
  "ref": [
  "out": [
  "del": [],
  "cre": [
  "exec": [
        "op": "DEPLOY",
        "data": ["class A extends Jig { }", { "deps": { "Jig": { "$jig": 0 } } }]
        "op": "NEW",
        "data": [{ "$jig": 1 }, []]

metadata(rawtx: string): object

Extracts all Layer-2 metadata from a RUN transaction. The metadata function will throw an error if not passed a valid RUN transaction in hex format. This method may be useful for debugging purposes and to determine whether a transaction is a RUN transaction. The metadata returned is not intended to be executed outside Run. This metadata is stored in the first output using OP_RETURN. For more about this data structure, see How It Works. The metadata function may be accessed via Run.util.metadata.


Use the optimized SHA-256

Run.util.sha256 = data => crypto.subtle.digest('SHA-256', Uint8Array.from(data))

sha256(data: Array<number>): Array<number>

The function that Run calls to perform SHA256 hashing internally. By default, this runs in the same process as Run, but it is possible to set a custom function that performs SHA256 in a background process. This may be useful in the browser to reduce UI stutter, or to used a more optimized SHA-256 implementation. The function takes and returns arrays of bytes.


Unify a token with its latest class

Run.util.unify(token, LatestTokenClass)

Unify dependencies so that two classes can be deployed together

run.transaction(() => {
  Run.util.unify(Axe, Sword)


unify(...creations: Array<Creation>)

Synchronizes the creations passed so that they all refer to the same objects in the same state. Run will prefer newer states over older states, so this is a quick way sync a jig to use its latest class if there is an upgrade. It may also be necessary to unify creations when using a Transaction.

Then RUN protocol requires that creations be unified within a transaction. This is usually performed automatically by Run before each method is executed, but only for the creations that interact in that method.



The Run Explorer lets you view jigs and code both on mainnet and testnet. It is an excellent way to test that your objects are working. To give it a go, open and click Explorer. Then, paste any location, address, or transaction ID into the search box.


Tokenkit is a standalone library with a set of tools to make it as simple as possible to create, deploy and mint fungible and non-fungible tokens. It offers a number of convenience functions that make it easy to combine, send and burn tokens. It also boasts a built-in api for working with the RelayX DEX to find, buy and sell tokens. Head over to the documentation on github to get started.


Run-DB is an indexer for jigs your app cares about. You can use it to precalculate the states of jigs so that they load quickly in your application or server. Most apps will either host their own Run-DB or use a third-party indexer like the Run State API. To get started, visit the github.

Easy B

The Easy B CLI tool and library lets you to upload files to the blockchain in the B:// format. This is great if you want to upload images, 3D models, or music to attach as metadata on your jigs. To give it a go, download it via NPM here and check out the corresponding docs.