js2rho

Apr 2020 by Dan Connolly

StakingPool.rho

a slog...

new deployResult, // (`rho:rchain:deployId`),
StakingPool,
RevAddress(`rho:rev:address`),
regInsert(`rho:registry:insertArbitrary`),
registryLookup(`rho:registry:lookup`),
stdout(`rho:io:stdout`),
RevVaultCh,
AuthKeyCh,
ListOpsCh
in {
  registryLookup!(`rho:rchain:authKey`, *AuthKeyCh) |
  // // regLookup!(`rho:lang:listOps`, *ListOpsCh) |
  registryLookup!(`rho:rchain:revVault`, *RevVaultCh) |
  for(
    @(_, AuthKey) <- AuthKeyCh;
    @(_, *RevVault) <- RevVaultCh
  ) {
    contract StakingPool(@"create", unsealer /*TODO: many unsealers*/, ret) = {
      stdout!({"create unsealer": *unsealer}) |
      new self, unf, revAddrCh, v1Ch, balanceCh, authKeyCh in {
        RevAddress!("fromUnforgeable", *unf, *revAddrCh) |
        RevVault!("unforgeableAuthKey", *unf, *authKeyCh) |
        for (@revVaultAuthKey <- authKeyCh; @revAddr <- revAddrCh) {
          stdout!({"new staking pool rev addr": revAddr, "authKey": revVaultAuthKey}) |
          RevVault!("findOrCreate", revAddr, *v1Ch) |
          for (@(true, *vault) <- v1Ch) {
            stdout!({"vault": *vault}) |
            ret!(bundle+{*self}) |

            /* TODO: go beyond just testing the vault mechanics... */
            contract self(@"redeem", @targetAddr, @amount, @sealedOrder, ret) = {
...

Agoric builds on JavaScript, Cosmos

JavaScript

  • Smart Contracts
    • Agoric
  • Capability Security
  • Mint, Purse
  • ERTP - Electronic Rights Transfer Protocol
  • Zoe - offer safety
  • ...

Rholang

  • Smart Contracts
    • RChain
  • Capability Security
  • Mint, Purse
  • Vault
  • PoS.rho - Proof of Stake
  • ...

StakingPool.js

port .rho -> .js by hand

/**
 * StakingPool contract
 *
 * This is reverse-translated from StakingPool.rho as a use case for a
 * JavaScript-to-Rholang compiler in progress.
 */

import { bundlePlus, tuple, console } from '@rchain-community/js2rho';
import { harden } from '@agoric/harden';
import { E } from '@agoric/eventual-send';

import deployResult from 'rho:rchain:deployId';
import RevAddress from 'rho:rev:address';
import regInsert from 'rho:registry:insertArbitrary';
import registryLookup from 'rho:registry:lookup';

export default
async function main() {
    const [{_0: _a, _1: AuthKey}, {_0: _r, _1: RevVault}] = await Promise.all([
        // TODO: uri('rho:...') along with tuple
        E(registryLookup)('rho:rchain:authKey'),
        E(registryLookup)('rho:rchain:revVault'),
    ]);
//...
}

js2rho.js

started 2018-04 (4c80b57)

connolly@jambox:~/projects/js2rho$ npm test

> js2rho@0.1.0 test /home/connolly/projects/js2rho
> node test/testSuite.js

==== TEST CASE:  StakingPool
js input: 3196 /** StakingPool contract
 * This is reverse-translated
DEBUG: js.type Program
{ Program: 8 }

==== DONE:  StakingPool

==== TEST CASE:  check_balance
js input: 682 import { tuple } from '@rchain-community/js2rho';

DEBUG: js.type Program
{ Program: 4 }

==== DONE:  check_balance

StakingPool.rho

generated from StakingPool.js via js2rho

new deployResult(`rho:rchain:deployId`),
RevAddress(`rho:rev:address`),
regInsert(`rho:registry:insertArbitrary`),
registryLookup(`rho:registry:lookup`),
console(`rho:io:stdout`)
in {
  
  new CallExpression_32c8_0, CallExpression_33c8_1
  in {
    registryLookup!("rho:rchain:authKey", *CallExpression_32c8_0) |
    registryLookup!("rho:rchain:revVault", *CallExpression_33c8_1) |
    for(@{ (*_a, *AuthKey) } <- CallExpression_32c8_0; @{ (*_r, *RevVault) } <- CallExpression_33c8_1) {      
      new StakingPool
      in {
        contract StakingPool(@{ "create" }, unsealer, __return) = {          
          new unf in {
            new CallExpression_40c16_2, CallExpression_41c16_3
            in {
              RevAddress!("fromUnforgeable", *unf, *CallExpression_40c16_2) |
              RevVault!("unforgeableAuthKey", *unf, *CallExpression_41c16_3) |
              for(revVaultAuthKey <- CallExpression_40c16_2; revAddr <- CallExpression_41c16_3) {
                console!({"new staking pool rev addr": *revAddr, "authKey": *revVaultAuthKey})
//...
}

JavaScript

Rholang

console.log('Hello, world!');
new console(`rho:io:stdout`)
in {
  console!("Hello, world!")
  }

JavaScript

Rholang

...
new
rInsert(`rho:registry:insert`)
, ch
in {
  rInsert!(???, *ch) |
  for (uri <- ch) {
    console!({"uri": *uri})
  }
}

JavaScript

Rholang

import rInsert
  from 'rho:registry:insertArbitrary';

import { E } from '@agoric/eventual-send';

const uri =
  await E(regInsert)(???);

console.log({ "uri": uri });
new
rInsert(`rho:registry:insert`)
, ch
in {
  rInsert!(???, *ch) |
  for (uri <- ch) {
    console!({"uri": *uri})
  }
}

JavaScript




import { E } from '@agoric/eventual-send';

const uri =
  await E(regInsert)(???);

tc39/proposal-eventual-send

E and E.sendOnly convenience proxies

 

proxies / promises

check_balance.rho

new rl(`rho:registry:lookup`), RevVaultCh,
  vaultCh, balanceCh,
  stdout(`rho:io:stdout`)
in {
    stdout!(("2.check_balance.rho")) |
  rl!(`rho:rchain:revVault`, *RevVaultCh) |
  for (@(_, RevVault) <- RevVaultCh) {

    match "%REV_ADDR REPLACE ME" {
      revAddress => {
        @RevVault!("findOrCreate", revAddress, *vaultCh) |
        for (@(true, vault) <- vaultCh) {
          @vault!("balance", *balanceCh) |
          for (@balance <- balanceCh) {
            stdout!(("Balance is", balance))
          }
        }
      }
    }
  }
}

check_balance.js

import { tuple } from '@rchain-community/js2rho';
import rl from 'rho:registry:lookup';

import E from '@agoric/eventual-send';

export default
async function main() {
    console.log("2.check_balance.rho");
    const { _0: _, _1: RevVault } = await E(rl)('rho:rchain:revVault');


    const revAddress = "%REV_ADDR";

    const { _0: ok, _1: vault } = await E(RevVault).findOrCreate(revAddress);
    switch (ok) {
        case true:
            const balance = await E(vault).balance();
            console.log(tuple("Balance is", balance));
    }
}

JS Dev Tools

  • Editors
    • but: vs-code .rho support is pretty good
  • Debuggers
    • but: need js runtime for registry etc.
  • Type checkers
    • until rholang types arrive

ERTP Contracts

  • atomicSwap.js
  • automaticRefund.js
  • autoswap.js
  • coveredCall.js
  • multipoolAutoswap.js
  • operaConcertTicket.js
  • publicAuction.js
  • simpleExchange.js

agoric-sdk/.../packages/zoe/src/contracts

ERTP Contracts

  • semi-automatic port
  • ...
  • add js support to rnode?
  • cross-chain interop w/cosmos?