encode

Creates a transaction according to the Bitcoin Computer protocol.

Type

;(opts: {
  exp: string // an expression
  env?: Record<string, string> // a blockchain environment
  mod?: string // a module specifier

  // Funding options
  fund?: boolean // whether to fund the transaction
  include?: string[] // include specific UTXOs when funding
  exclude?: string[] // exclude specific UTXOs when funding

  // Signing options
  sign?: boolean // whether to sign the transaction
  sighashType?: number // signature hash type to use
  inputIndex?: number // input index to be signed
  inputScript?: Buffer // use input script (instead of signing)

  // Mock options
  mocks?: Record<string, any> // values to mock
}) =>
  Promise<{
    // the transaction with the expression inscribed
    tx: NakamotoJS.Transaction

    // the result of the evaluation
    effect: { res: unknown; env: { [s: string]: unknown } }
  }>

Parameters

opts

An object with a specification to build a transaction according to the Bitcoin Computer protocol.

Key Description Default
exp A JavaScript expression. -
env A Blockchain environment mapping variables names to revisions. {}
mod A string of the form <id>:<num> specifying the location of a module (see propagation rules). undefined
fund Whether the transaction should be funded. true
include UTXOs to include when funding. []
exclude UTXOs to exclude when funding. []
sign Whether to sign the transaction. true
sighashType The signature hash type. SIGHASH_ALL
inputIndex If set to an number only the corresponding input is signed. If undefined all inputs are signed. undefined
inputScript If set to a string a custom input script can be provided. If undefined a signature script is generated. undefined
mocks A pair <name, object>. The object is an instance of a mocked class (A class that does not extends from Contract but has the keywords _id, _root, _satoshis,_owners) {}

Return Value

It returns an object { tx, effect } where tx is a NakamotoJS transaction and effect is an object with keys res and env. The res object contains the result of the evaluation. The env object has the same keys as the blockchain environment. However, whereas the values of the blockchain environment are revision strings, the values of env and the smart object at these revisions after evaluating the expression.

Description

The encode function builds a Bitcoin transaction from a JavaScript expression. It returns a transaction and an object effect containing the result of the evaluation in a property res. If the expression contains undefined variables a blockchain environment env must be passed into encode. A blockchain environment maps the named of the undefined variable to UTXOs containing on-chain objects. A module specifier can be provided in order to make the exports of that module are available to the evaluation.

When a module specifier mod is supplied to encode, all objects that are created in the transaction are associated with that module specifier. The module specifier never changes, even when the object it updated. It is important to note that if an object o1 created a second object o2 in a method call, o2 does not automatically inherit o1's module specifier. If this is desired, then module specifier needs to be passe into the expression encoding the function call. For example, the transfer function of the TBC20 contract creates a new object for the receipient. This object will not inherit the module specifier of the original token. If this is desired the module specifier needs to be passed into the encode call of the transfer function.

Other options can customize the funding and signing process. It is also possible to pass in an object specifying mocked objects.

It is important to note that encode does not broadcast the transaction. Nonetheless the effect object reflects the on-chain state that will emerge once the transaction is broadcast.

Example

import { Computer, SmartContract, Contract } from '@bitcoin-computer/lib'
import { chain, expect, network, url } from '../../utils/index.js'

describe('encode', () => {
  let computer: Computer

  before('Create and fund wallet', async () => {
    computer = new Computer({ chain, network, url })
    await computer.faucet(1e8)
  })

  // Objects
  it('Should work for a class', async () => {
    // A smart contract
    class Counter extends Contract {
      n: number

      constructor() {
        super({ n: 0 })
      }

      inc() {
        this.n += 1
      }
    }

    // Encode a constructor cal
    const { effect: e1, tx: tx1 } = await computer.encode({
      exp: `${Counter} new Counter()`,
    })

    // Broadcast the transaction
    const txId1 = await computer.broadcast(tx1!)

    // As above, synchronizing to a transaction id always returns the effect
    expect(await computer.sync(txId1)).deep.eq(e1)

    // The result of effect e1 is a counter
    const counter = e1.res as SmartContract

    // Encode a function call incrementing the counter
    const { effect: e2, tx: tx2 } = await computer.encode({
      // The expression
      exp: `c.inc()`,

      // The value for the counter is stored at counter._rev
      env: { c: counter._rev },
    })

    // As before we can broadcast the transaction to update the on-chain state
    const txId2 = await computer.broadcast(tx2!)

    // The sync function reads the on-chain state
    expect(await computer.sync(txId2)).deep.eq(e2)
  })
})

Source