kadena-community / kadena.js

Public monorepo for all Typescript/Javascript related tools and libs for Kadena
https://docs.kadena.io
BSD 3-Clause "New" or "Revised" License
34 stars 24 forks source link

Pact javascript client/generator #46

Open alber70g opened 2 years ago

alber70g commented 2 years ago

I started on a tool that, based on Typescript definitions, would be able to generate Pact expressions.

Inspired by Prisma ORM, that generates a type-safe client based on a database schema (see example)

We would be able to generate a type definition from all modules available on the blockchain (edit: using ASTs from Pact(?)). This allows users to make the right type-safe calls. Those are intercepted by a Proxy, that returns either Pact code or even a client that can execute the call to the chainweb-node API.

PoC: #45

This could be something like

const generator = Pact.coin.transfer("k:sender", "k:receiver", 4.5)
generator.client({ chainId, networkId }).sign().call() // create client, maybe sign, and post to chainweb-node
generator.generate() // returns (coin.transfer "k:sender" "k:receiver" 4.5)

Thoughts:

mightybyte commented 2 years ago

Here are some thoughts that jump out at me at first glance...

The first is that I think the specific case of the above example should be generalized from coin to arbitrary fungibles. Using the above as a template, here's what I think it would look like:

const generator = Pact.fungible.transfer("coin", "k:sender", "k:receiver", 4.5)
generator.client({ chainId, networkId }).sign().call() // create client, maybe sign, and post to chainweb-node
generator.generate() // returns (coin.transfer "k:sender" "k:receiver" 4.5)

Secondly, signing is always going to be tricky. There will be some situations where you can just sign because you have the key, but there will be many situations where you can't sign. So the above .sign() is probably overly simplistic and will eventually need to deal with the WalletConnect signing API that @jmininger is working on. It's already tricky in that context but it gets even more tricky with multi-sig where multiple signatures have to be assembled.

We can think of the overall flow as:

  1. Transaction construction
  2. Transaction signing
  3. Transaction submission

Here's the really annoying wrinkle. In the case of multi-sig, step #1 becomes more complicated because if you have a keys-any multi-sig account, you'll need to decide which key you want to sign with in step #1, well before you actually get to the business of signing. To see an example of how we've dealt with this in practice, play around with doing a Chainweaver transfer on testnet from a multi-sig account. There's a screen where you have to select the key that you want to sign with and that has to happen before the transaction's request key can be finalized.

The third and most problematic issue here is that this idea of a generic transaction generator is probably not feasible right now because we don't yet have a way to automatically figure out which capabilities are needed for a transaction to be valid. There has been some talk in the past about making something that can automatically extract the necessary capabilities, but that has not been implemented yet and will definitely be a non-trivial endeavor. So full auto-generation of transaction templates from Pact modules is probably much longer-term stretch goal.

sirlensalot commented 2 years ago

An immediately actionable improvement would be to get better reflection from describe-module https://github.com/kadena-io/pact/issues/1017

alber70g commented 2 years ago

Here are some thoughts that jump out at me at first glance...

The first is that I think the specific case of the above example should be generalized from coin to arbitrary fungibles. Using the above as a template, here's what I think it would look like:

const generator = Pact.fungible.transfer("coin", "k:sender", "k:receiver", 4.5)
generator.client({ chainId, networkId }).sign().call() // create client, maybe sign, and post to chainweb-node
generator.generate() // returns (coin.transfer "k:sender" "k:receiver" 4.5)

Several thoughts:

Secondly, signing is always going to be tricky. There will be some situations where you can just sign because you have the key, but there will be many situations where you can't sign. So the above .sign() is probably overly simplistic and will eventually need to deal with the WalletConnect signing API that @jmininger is working on. It's already tricky in that context but it gets even more tricky with multi-sig where multiple signatures have to be assembled.

For the above .sign() we've thought of creating a sign-provider that can be passed to the Pactjs instance. Or when the sign is called, the consumer can pass a signer function: .sign(toBeSignedString => arbitraryFunctionToSign(toBeSignedString)). When multi-sig is involved we can provide a "hook" to allow external tools/mechanisms to sign for other caps.

We can think of the overall flow as:

  1. Transaction construction
  2. Transaction signing
  3. Transaction submission

Here's the really annoying wrinkle. In the case of multi-sig, step #1 becomes more complicated because if you have a keys-any multi-sig account, you'll need to decide which key you want to sign with in step #1, well before you actually get to the business of signing. To see an example of how we've dealt with this in practice, play around with doing a Chainweaver transfer on testnet from a multi-sig account. There's a screen where you have to select the key that you want to sign with and that has to happen before the transaction's request key can be finalized.

We probably need to find a way to form transactions in a asychronous manner when multi-sig is involved.

The third and most problematic issue here is that this idea of a generic transaction generator is probably not feasible right now because we don't yet have a way to automatically figure out which capabilities are needed for a transaction to be valid. There has been some talk in the past about making something that can automatically extract the necessary capabilities, but that has not been implemented yet and will definitely be a non-trivial endeavor. So full auto-generation of transaction templates from Pact modules is probably much longer-term stretch goal.

We can provide a template library (like tx-library) that can be part of the generation process. The generator should be able to consume multiple of those libraries, so no one is dependent on us to provide these templates.

These templates could also help with multi-sig transactions

====

In general, to provide unlimited acccess to chainweb ecosystem, for the js-community, we need to create an interface/bridge. I think providing the tools that allow them to use the network, will increase usability, and thus use of the blockchain. Right now, people are struggeling to find ways to make use of the blockchain, and I believe a library can take away these concerns.

github-actions[bot] commented 2 years ago

This issue is stale because it is open for 60 days with no activity