rchain-community / rchain-api

An API for rchain dapps to communicate with the blockchain
Other
22 stars 12 forks source link

How to get value from registry ? #32

Open fabcotech opened 5 years ago

fabcotech commented 5 years ago

In another contract I stored a value in the registry:

new
  uriChan,
  insertArbitrary(`rho:registry:insertArbitrary`),
  stdout(`rho:io:stdout`) in {

  // Tell the registry that we want to register
  // give URI back on uriChan
  insertArbitrary!(bundle+{"coucou"}  , *uriChan) |

  // Wait for URI response
  for(@uri <- uriChan) {
    stdout!(uri)
  }
}

The returned address is rho:id:pmc1cn6zff1pk5sf3purwby4zuqmwdiaj5xd7mu55usk88q5be9and

How can I get this value back in a node JS / web browser context using the rchain-api.js library ? Is it by using the listenForDataAtPublicName or listenForDataAtPrivateName api ? Or something else ?

dckc commented 5 years ago

good question! I hope we have a clear example / test for this soon.

Yes, listenForDataAtName is an essential part of the answer, but previewPrivateNames is another piece that's emerging.

JoshOrndorff commented 5 years ago

@fabcotech The high-level overview is this:

  1. Send the uri to some channel other than standard out
  2. Use listen...AtName to read the uri off the blockchain.

The best solution is to use a private name as @dckc suggested. Another option that may be easier for initial testing is to use a public name.

Some examples of these techniques are in our live node test https://github.com/rchain-community/rchain-api/blob/master/test/liveRNodeTest.js#L48

You've given me a big push toward writing proper docs for this package!

fabcotech commented 5 years ago

Ok here is how I did it !

Store the value on the chain:

const rchain = RNode(grpc, {
  host: HOST,
  port: PORT,
});

const code = `
  new
    uriChannel,
    private,
    receiverChannel,
    lookup(`rho:registry:lookup`),
    insertArbitrary(`rho:registry:insertArbitrary`),
    stdout(`rho:io:stdout`) in {
      insertArbitrary!("store this data" , *uriChannel) |

      for(uri <- uriChannel) {
        lookup!(*uri, *receiverChannel) |
        for(value <- receiverChannel) {
          private!(*value) |
          @"publicChannel"!(*private)
        }
      }
  }`;

rchain
    .doDeploy({
      term: code,
      timestamp: clock().valueOf(),
      from: "0x1",
      nonce: 0,
      phloPrice: { value: 1 },
      phloLimit: { value: 100000 }
    })
    .then(deployMessage => {
      return rchain.createBlock();
    })
    .then(blockCreated => {
      console.log("block created");
    });

Retreive the value:

rchain
  .listenForDataAtPublicName("publicChannel")
  .then(blockResults => {
    return blockResults[0].postBlockData.slice(-1).pop();
  })
  .then(privateName => rchain.listenForDataAtName(privateName))
  .then(blockResults => {
    blockResults.forEach(b => {
      b.postBlockData.forEach(d => {
        logged("Value retreived : ", RHOCore.toRholang(d));
      });
    });
  });
ziqiDev commented 5 years ago

met with the same problem. how to convert ids in Par to string ?

dckc commented 5 years ago

@fabcotech that looks pretty close to the techniques I use in proxy.js, except that I use unforgeable names rather than public names.

@ziqiDev writes:

how to convert ids in Par to string ?

/**
 * Get printable form of unforgeable name, given id.
 */
exports.unforgeableWithId = unforgeableWithId;
function unforgeableWithId(id /*: Uint8Array */) {
  const bytes = Writer.create().bytes(id).finish().slice(1);
  return `Unforgeable(0x${b2h(bytes)})`;
}

exports.prettyPrivate = prettyPrivate;
function prettyPrivate(par /*: IPar */) {
  if (!(par.ids && par.ids.length && par.ids[0].id)) { throw new Error('expected GPrivate'); }
  return unforgeableWithId(par.ids[0].id);
}

(currently in loading.js, moving to proxy.js in 1ce2a4395341563d34069c9737b9386f8f43ec83)

ziqiDev commented 5 years ago

I see, but I want to convert it to rho:id:shfe667fqiak6g9e1iy.....

dckc commented 5 years ago

rho:id:shfe66... is not an unforgeable name. In a Par, it shows up as g_uri.

ziqiDev commented 5 years ago

rho:id:shfe66... is not an unforgeable name. In a Par, it shows up as g_uri.

Could I get g_uri through api ?

dckc commented 5 years ago

yes, with toJSData.

I just (5878af2) added examples to the RHOCore section of the API docs. The Uri and ByteArray example should clarify:

const { URL } = require('url');
const { RHOCore, Hex } = require('rchain-api');

const data = [new URL('rho:id:123'), Hex.decode('deadbeef')];
const rhoProto = RHOCore.fromJSData(data);
assert.deepEqual(RHOCore.toJSData(rhoProto), data);
assert.equal(RHOCore.toRholang(rhoProto),
    '[`rho:id:123`, "deadbeef".hexToBytes()]');