Everything in this master branch was coded until the 17.2.2023 (Polkadot Global Series deadline date).

To see the recent changes, go to the Devel branch.

PlutoWallet

A sample wallet that implements Plutonication.

Supported platforms:

  • Android & WearOS
  • iOS & ipadOS
  • MacCatalyst
  • Windows

The wallet supports these functionalities:

  • generating Mnemonics & creating a privateKey
  • showing and sharing your public key and ss58 key
  • connecting to any substrate based blockchain/parachain
  • getting your actual balance
  • simple transfer

3rd party integrations:

Allows any dApp to communicate with supported wallets without compromising private keys. It was designed for a specific purpose, but can also be used for general solutions that need to achieve a level of abstraction with TCP communication.

Terminology

  • dApp = any application that wants to use the crypto functionalities. In order to use dApps, it needs to communicate with the crypto wallet somehow, or it needs to know your private key (very insecure).

Work / milestones

part 1 - Plutonication (Pluto connector)

Note for development: to update git submodule, run: git submodule update --remote

  1. Create a simple dApp to test the connection between the Wallet and dApp.
  2. Find out how to connect the 2 apps via WebSocket (look into resources) - solved via TCP protocol.
  3. Create the 2 basic call operations/methods:
  • SendMessage(PlutoMessage{Code, Data})
  • ReceiveMessage(PlutoMessage{Code, Data})
    • where code is ID which determinate type of message. Data are content of message.
  1. Make this a modular package -> release to Nuget.
  2. Class with URI link (containing IP address, port, and authentication token).
  • Also allow parameters: Name (dApp name), Icon (URL to dApp icon). These two params may help identify the nature of the incoming transaction when scanning QR code.
  • QR code generation will probably be part of PlutoWallet.
  1. Convert to async.
  2. Create safe listen+connection.
  • Wallet (client): Connect(ipAddress, port, auth), dApp (server): StartServer(port, auth)
  • Listen will compare received auth with held auth. If match: OK, else: don't match -> kick.
  1. create client which handles infinite receive loop completely. Event driven architecture:
  • Start (Connect/Listen), which will pair automatically using given credentials and set up a loop that will receive messages (until CloseConnection is called).
  • Include Recv. message event.
  • ConnectionClosed event.
  • ConnectionEstablished event.
  1. Experimental object class sending including object serialization (Status: deserialization is unreliable. May work on this feature in the future. May use a totally different approach. See the issue here, branch here)

  2. nuget package

  3. ip address on android devices

  4. (VERY IMPORTANT) create a very detailed (and begginer friendly) documentation with how to use it and add examples

  5. polkadot js integration (ask Rosťa for more)

  6. make a javascript version

Usecases
  1. pair devices
  2. send publickey to wallet (string)
  3. send transaction <"header",byte, byte, byte[]> from dApp to wallet:
  • wallet y/n -> response (failed due sth/rejected/accepted )
  • dApp: display status of transaction (response)
  1. both wallet and dApp are able to send data in form of:
  • byte[] byte array
  • string
  • alone MessageCode enum (can be used for example to send confirmation with MesageCode.Success, MessageCode.Refused, MessageCode.FilledOut)
  1. close connection (from both sides):
  • on connection lost event
  • throws exceptions in proper cases/places
QR code docs (format):
  1. Starts with plutonication:
  2. Query parameters:
  • url = dApp url to connect to (with port), example: url=192.168.0.1:1234
  • key = password key to connect, example: key=password123
  • name (optional) = dApp name, example: name=Galaxy logic game
  • icon (optional) = dApp icon url example: icon=http://rostislavlitovkin.pythonanywhere.com/logo

A complete example: plutonication:?url=192.168.0.1:8000&key=password123&name=Galaxy logic game&icon=http://rostislavlitovkin.pythonanywhere.com/logo

part 2 - PlutoWallet

  1. generate mnemonics and show it to the user
  2. enter mnemonics
  3. enter private key
  4. show the user raw privateKey
  5. save the privateKey securely
  6. (extra) secure with password/biometrics
  7. generate a publicKey from the privateKey
  8. (extra - EASY) make ss58 encoded publicKeys
  9. get the current balance
  10. (extra) show the balance in USD (use coingecko free api)
  11. add a transfer functionality
  12. add the ability to sign any transaction (Can be done through plutonication)
  13. QR scanner
  14. improve UI
  15. further improve UI
  16. add multiple chain support
  17. (extra) the ability to add other unknown chains manually
  18. (extra) NFT implementation
  19. show other funganble tokens
  20. plutonication deep link
  21. add loading animations
  22. icon and splash screen
  23. implement nicks pallet
  24. show basic error messages
  25. show more error messages
  26. XCM
  27. credits
  28. more animations
  29. update the color theme
  30. change button names to icons

Other milestones

#1 NFTs integration

  • show all owned NFTs
  • allow minting your own NFTs
  • NFT dex implementation

#2 Staking

  • show stake pools
  • show gains
  • more...

#3 dApp gallery

  • dApp promotion page

#4 Voting

#5 ink!

#6 buy crypto

(extra) part 3 - browser extension

Acts like any other browser wallet, with the functionality of connecting to Web dApps, but instead of storing a private key, will generate a QR code for Plutonication. It will then pass all the requested data to the PlutoWallet.

part 4 - video and presentation

Resources to use

Hackathon:

Socket solutions:

Polkadot solutions:

Blockchain communication tools

parity signer

NFTs

Inspiration:

Sample transfer to be implemented:

public static Method Transfer(AjunaExample.NetApiExt.Generated.Model.sp_runtime.multiaddress.EnumMultiAddress dest, Ajuna.NetApi.Model.Types.Base.BaseCom<Ajuna.NetApi.Model.Types.Primitive.U128> value)
        {
            System.Collections.Generic.List<byte> byteArray = new List<byte>();
            byteArray.AddRange(dest.Encode());
            byteArray.AddRange(value.Encode());
            return new Method(5, "Balances", 0, "transfer", byteArray.ToArray());
        }