Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pact javascript client/generator #46

Open
alber70g opened this issue Jul 14, 2022 · 4 comments
Open

Pact javascript client/generator #46

alber70g opened this issue Jul 14, 2022 · 4 comments
Labels
discussion Needs (architectual) discussion to make a decision no-issue-activity

Comments

@alber70g
Copy link
Member

alber70g commented Jul 14, 2022

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:

  • we could generate the client as well instead of using a Proxy (I believe Prisma generates their client as well. Not 100% sure though)
  • the generator could be completely separate from the client
  • ...
@alber70g alber70g added the discussion Needs (architectual) discussion to make a decision label Jul 15, 2022
@mightybyte
Copy link

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
Copy link

An immediately actionable improvement would be to get better reflection from describe-module kadena-io/pact#1017

@alber70g
Copy link
Member Author

alber70g commented Jul 21, 2022

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:

  • I'd like the ts language reflecting the actual statements as close as possible. Using fungibles, adds a layer of opaqueness that isn't necessary
  • Given that we generate the Pact-expression-builder, I don't see the value in creating an abstracting over fungibles.
  • On top of that, it adds an extra layer of complexity during generation. We have to determine what interface is implemented by a given module. Make a specific branch to determine how this should be formed in typescript definition. The runtime has to have specialized way to generate the expression when that function is called.

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
Copy link
Contributor

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion Needs (architectual) discussion to make a decision no-issue-activity
Projects
None yet
Development

No branches or pull requests

3 participants