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

NEP: dApp Platform Provider Interface #69

Closed
wants to merge 97 commits into from

Conversation

@nickfujita
Copy link

@nickfujita nickfujita commented Oct 3, 2018

A proposal for a standardized protocol interface between dApp developers and dApp API platform providers.

@nickfujita nickfujita changed the title dApp Platform Provider Interface NEP: dApp Platform Provider Interface Oct 3, 2018
nep-dapi.mediawiki Outdated Show resolved Hide resolved
Loading
nep-dapi.mediawiki Outdated Show resolved Hide resolved
Loading
nep-dapi.mediawiki Outdated Show resolved Hide resolved
Loading
nep-dapi.mediawiki Outdated Show resolved Hide resolved
Loading
Copy link

@evgenyboxer evgenyboxer left a comment

Great job!

Here are couple of other useful methods: (all are promises)

  1. signMessage - Given a payload, allow the user to sign the message contents.
  2. getNetwork - Returns the users network - MainNet/TestNet/PrivateNet.
  3. isLoggedIn - Returns true if logged in.
  4. isReady - Might be specific to nex extension, but there are certain checks that need to be done before accepting calls from the dapp.

Events:

  1. network_changed - fired when a user changes his network.
  2. account_changed - fired when a user logs in/out.
  3. ready - fired when the provider is ready.

let me know what you think @nickfujita

Loading

nep-dapi.mediawiki Outdated Show resolved Hide resolved
Loading
nep-dapi.mediawiki Outdated Show resolved Hide resolved
Loading
@corollari
Copy link
Contributor

@corollari corollari commented Aug 6, 2019

Also, it may be interesting to add some method to get the current block but this is not important.

Loading

@igormcoelho
Copy link

@igormcoelho igormcoelho commented Aug 6, 2019

Thanks for the responses @nickfujita.. my intent was trying to maje it better,although I know its a challenge to change things that many providers are already using... others are directly connected to neo rpc standard,which is not perfect too.
On general, a smart dev can use any.sort of api, as long as things are explained.

This looks like a good standard afterall, due to all these limitations, and perhaps we should just close all my comments, since this is a "nearly final" proposal (no need to change small things). Congratulations.

Loading

@nickfujita
Copy link
Author

@nickfujita nickfujita commented Aug 7, 2019

@corollari

Great point! I am also very much in agreement with this. Rather than injecting the latest version of the method interface onto the window of the dApp website, providers should be providing properly versioned packages.

In the case of O3, we currently utilize NPM and CDN (JSDeliver) to ensure that dApps can protect themselves from sudden changes in the interface. In this way, dApps can lock down their NPN dependencies, or reference a specific version of the CDN package to pull into their website.

NPM

CDN

Although this is how O3 choose to implement this, since the proposal is still just focused on the interface of the methods themselves, it is not currently a requirement.

Do others think that we should add this as a requirement to the proposal, or should it just be left as a general "best practice" for dApps and websites in general for importing JS dependencies?

Loading

@canesin
Copy link

@canesin canesin commented Aug 7, 2019

I think that @corollari comment is on point. About an year ago I suggested that the provider should inject versioned libraries but if instead we can have a versioned provider object (as capabilities of the provider can change in time also) that the API library can consume instead is much better. Nash would be willing to support the standard if we adopt that model and ship a new version of neon-js that accept the provider object instead of current system.

Loading

@nickfujita
Copy link
Author

@nickfujita nickfujita commented Aug 9, 2019

@corollari Added getBlockHeight

Loading

@nickfujita
Copy link
Author

@nickfujita nickfujita commented Aug 9, 2019

@igormcoelho Thanks again for all the input. It was very helpful, and a bunch of improvements were made to the proposal per your feedback ^^

Loading

@nickfujita
Copy link
Author

@nickfujita nickfujita commented Aug 9, 2019

@canesin We are all excited for the launch of your platform this month, and are glad you have circled back to this proposal. I've added to the proposal a spec which briefly describes how providers of client packages should be versioning and supporting this interface.

As for the integration into neon-js, we would be happy to provide any additional documentation required for the integration team.

Loading

@corollari
Copy link
Contributor

@corollari corollari commented Aug 11, 2019

@nickfujita Looks good, sent a PR fixing several typos and grammar problems (all trivial changes).

Loading

@nickfujita
Copy link
Author

@nickfujita nickfujita commented Aug 13, 2019

@corollari Thanks! Merged in!

Loading

@hal0x2328
Copy link
Contributor

@hal0x2328 hal0x2328 commented Sep 9, 2019

encrypt and decrypt methods would be very useful, so dApps can have a seamless encrypted messaging feature. This is something that is already available in the nOS API, and I'm using it for my Safe Remote Purchase dApp. I'd like to port that dApp to use the dAPI protocol but the lack of built-in encrypt/decrypt of arbitrary messages would severely hinder its utility or require the dApp to store the user's private key in the browser, entirely defeating the purpose of using dAPI.

Loading

@corollari
Copy link
Contributor

@corollari corollari commented Sep 11, 2019

@hal0x2328 There might be some problems with that, this interface aims to support wallets that use Ledger Nano and currently the NEO app for Ledger Nano does not seem to support encryption/decryption^[1]. Thus the following solutions appear:

  • Include encrypt/decrypt and drop support for Ledger devices (at least partially, the api could return errors when trying to use encrypt/decrypt on ledger nano based wallets)
  • Write a new Ledger app for NEO and get users to migrate to that one instead of using the current one
  • Get an update to the Ledger nano NEO app merged upstream. This seems a bit hard as it would have to go through several security reviews from their team and even after it is accepted you'd have to get current users to download Ledger Live and update the NEO app.

Another solution for your use-case that uses the current API would be:

  • Generate public/private key pair client-side
  • Sign public key using the sign method of this api and send it over to the other client
  • Other client verifies and does the same
  • At this point you have established encrypted communications through the two clients and you have the private key directly at your disposal so you can do whatever you please with them.

Also note that this systems allows implementations to use any encryption scheme they want but integrating encrypt/decrypt would force an unique encryption system onto everyone (which isn't necessarily a bad thing given almost everyone just simply wants strong encryption).

Still, given that one of the biggest objectives of this NEP is to improve dev experience (and having to implement a Diffie-Hellman key exchange by yourself is not good dev UX) it may be interesting to consider one of the solutions I proposed.

[1]: I have not verified it directly from the source code (couldn't find it easily) so this might be wrong

Loading

@corollari
Copy link
Contributor

@corollari corollari commented Sep 11, 2019

@nickfujita would it be possible to describe in more detail how signMessage wraps the data inside a non-executable transaction and adds salt? I'm currently trying to implement the dAPI and I'm having trouble with that bit. It seems that the transaction as described in this NEP includes a randomized salt but in the description on how to build the signed message available in https://docs.switcheo.network/#signing-messages-for-neo it is not mentioned that any salt should me added or how should it be done.

I have also tried to look into how it's currently implemented in the source code but:

  • Couldn't find the source code for the desktop version of O3
  • Teemo implements an outdated version of this api that doesn't even include that operation
  • NeoLine implements an outdated version of the api (I submitted an issue in their repo)

Loading

@nickfujita
Copy link
Author

@nickfujita nickfujita commented Sep 16, 2019

@corollari here is the code to generate the signMeesage empty tx.

import { u } from '@cityofzion/neon-js';
import { v4 as uuid } from 'uuid';

function createSignMessage(message) {
  const salt = uuid().replace(/-/g, '');
  const parameterHexString = u.str2hexstring(salt + message);
  const lengthHex = u.num2VarInt(parameterHexString.length / 2);
  const concatenatedString = lengthHex + parameterHexString;
  const messageHex = '010001f0' + concatenatedString + '0000';

  return {
    messageHex,
    salt,
  };
}

Loading

@vincentOpenSource
Copy link

@vincentOpenSource vincentOpenSource commented Sep 16, 2019

  • 目前,DAPI的invoke方法需要传递的参数有scriptHash(合约hash),operation(方法名),arguments(参数数组)。 这就要求开发的合约的主函数必须有两个入参,一个参数是字符串,一个参数是数组。 但是,当前的合约编译是支持主函数拥有多个入参的。 由于NEOray 的合约调用模块是基于合约的,所有合约都需要兼容。 因此这里没有固定一个方法名参数和数组参数。 可以通过随意添加参数来生成调用所使用的参数。

  • Currently, DAPI's invoke method needs to pass parameters such as scriptHash, operation, and arguments. This requires that the main function of the developed contract must have two parameters, one parameter is a string, and one parameter is an array. However, the current contract compilation supports the main function with multiple input parameters. Since NEOray's contract calling module is contract-based, all contracts need to be compatible. So there is no fixed method name parameter and array parameter. You can generate the parameters used by the call by adding parameters at will.
    image

  • The following is the generated json code

[
   {
      "type": "String",
      "value": "test"
   },
   {
      "type": "Array",
      "value": [
         {
            "type": "Integer",
            "value": "1"
         }
      ]
   }
]
  • 建议增加以下接口用于实现main函数有多个入参的调用情况
  • It is recommended to add the following interface to implement the call of the main function with multiple parameters.
    image
    image

Loading

@hal0x2328
Copy link
Contributor

@hal0x2328 hal0x2328 commented Sep 16, 2019

@hal0x2328 There might be some problems with that, this interface aims to support wallets that use Ledger Nano and currently the NEO app for Ledger Nano does not seem to support encryption/decryption^[1]. Thus the following solutions appear:

* Include encrypt/decrypt and drop support for Ledger devices (at least partially, the api could return errors when trying to use encrypt/decrypt on ledger nano based wallets)

* Write a new Ledger app for NEO and get users to migrate to that one instead of using the current one

* Get an update to the Ledger nano NEO app merged upstream. This seems a bit hard as it would have to go through several security reviews from their team and even after it is accepted you'd have to get current users to download Ledger Live and update the NEO app.

...
[1]: I have not verified it directly from the source code (couldn't find it easily) so this might be wrong

I've verified the current Ledger Neo app does not currently support encrypt/decrypt but this might be a good time to implement it since the app will need an overhaul for Neo3 anyway.

I've seen that a few other cryptocurrencies Ledger apps do support encrypt/decrypt - they do so by letting the user authorize the app to generate and return the ECDH shared secret key for a sender/receiver pair, then the actual session encryption/decryption is handled in the wallet. This is probably necessary since the Ledger's memory is so limited and also it would be kind of a pain to authorize each and every message decrypt/encrypt especially in an ongoing chat log.

If this seems like a viable path I can add this code to the Neo Ledger app. My only issue is that I only have a Ledger Nano S and it would need to be tested on the Blue and Nano X also.

Loading

@corollari
Copy link
Contributor

@corollari corollari commented Sep 16, 2019

@vincentOpenSource Are you proposing that the dAPI should also support calling contracts with arbitrary parameters (eg: use a number for the first parameter) or just explaining how to use the current dAPI with NEOray's system?

Loading

@corollari
Copy link
Contributor

@corollari corollari commented Sep 16, 2019

@hal0x2328 To me that seems like a good idea but @nickfujita has probably better insights into that.
Regarding the problem with testing, I only own the Nano S as well so I can only help with testing on that device.

Loading

@vincentOpenSource
Copy link

@vincentOpenSource vincentOpenSource commented Sep 17, 2019

@vincentOpenSource Are you proposing that the dAPI should also support calling contracts with arbitrary parameters (eg: use a number for the first parameter) or just explaining how to use the current dAPI with NEOray's system?
Yes, I`m proposing that the dAPI should also support calling contracts with arbitrary parameters (eg: use a number for the first parameter)

Loading

@hal0x2328
Copy link
Contributor

@hal0x2328 hal0x2328 commented Sep 17, 2019

@hal0x2328 To me that seems like a good idea but @nickfujita has probably better insights into that.
Regarding the problem with testing, I only own the Nano S as well so I can only help with testing on that device.

Here's my fork of the Ledger app that adds an ECDH shared-secret generation function if anyone wants to have a look at potentially adding message encrypt/decrypt to dAPI.

https://github.com/hal0x2328/ledger-app-neo

Loading

@corollari
Copy link
Contributor

@corollari corollari commented Sep 25, 2019

Regarding the parameters of invokeMulti, it doesn't seem clear how can several triggerContractVerification, one for each InvokeArgument, play into the creation of a single transaction, especially given that there is only a single 0x20 attribute for any transaction^1 and having several triggerContractVerification with different values would mean that the value for such attribute could have different conflicting values. How is this resolved?

Several attachedAsset, one for each script call, are also a bit confusing, but I assume these are combined by creating different asset intents for the same transaction, each one pointing at the address of the script hash used in each specific call, is this right?

Loading

@corollari
Copy link
Contributor

@corollari corollari commented Oct 15, 2019

Created a PR that updates the implementation section: nickfujita#3

Loading

@nickfujita
Copy link
Author

@nickfujita nickfujita commented Oct 15, 2019

@QingmingZi Could you please confirm that your Teemo wallet is no longer being maintained?

Loading

<pre>
interface Networks {
networks: string[]; // Array of network names the wallet provider has available for the dapp developer to connect to.
Copy link
Member

@erikzhang erikzhang Jan 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this method should return the magic number of the networks. And also, maybe these data can be returned by getProvider().

Loading

Copy link
Member

@erikzhang erikzhang Jan 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loading

@erikzhang erikzhang closed this Jul 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet