What is Plutonication

                    Examples in C#
                

Plutonication allows users to connect PlutoWallet to other dApps seamlessly on any platforms, accross multiple codebases. DApp just generates a QR code and once it is scanned in the wallet, they will pair and the wallet will be able to receive transaction requests from the dApp. It works on the same principle as WalletConnect protocol.

Plutonication for C# is optimised for use with Substrate.NetApi or Polkadot.Unity.SDK. Be sure to get familiar with the respective guides to understand this guide to full extend. If you are not using any of these packages for your C# project, You must check them out!

Installation


using Plutonication;

// Other dependencies that were used for this demo
using Substrate.NET.Wallet;
using Substrate.NetApi;
using Substrate.NetApi.Generated;
using Substrate.NetApi.Generated.Model.sp_core.crypto;
using Substrate.NetApi.Generated.Model.sp_runtime.multiaddress;
using Substrate.NetApi.Generated.Storage;
using Substrate.NetApi.Model.Extrinsics;
using Substrate.NetApi.Model.Types;
using Substrate.NetApi.Model.Types.Base;
using Substrate.NetApi.Model.Types.Primitive;
                

Use this command: dotnet add package Plutonication or download it from the Visual Studio UI.

After the installation succeeds, do not forget to import it.

The following guide also uses Substrate.NetApi package. Other files were automatically generated by the Substrate.Net.Toolchain. You can follow this guide on how to generate your own substrate types for c#.

Access Credentials

                    
AccessCredentials ac = new AccessCredentials
{
    // Name of your dApp
    Name = "CSharp Plutonication console test",

    // Icon of your dApp
    Icon = "https://rostislavlitovkin.pythonanywhere.com/plutowalleticonwhite",

    // Address of Plutonication server
    // Feel free to use this one
    Url = "wss://plutonication.com/",
};



// Show the AccessCredentials to the wallet
Console.WriteLine(ac.ToUri());
                 

To use PlutonicationDAppClient, you need to provide the AccessCredentials with the necessary information.

But do not worry, it is this easy.

Feel free to use the wss://plutonication.com/ address. You might also choose to deploy your own Plutonication server. The guide on how to deploy it can be found here.

DApp name and dApp icon properties are shown in the wallet upon requesting connection.

Do not forget to somehow pass the access credentials to the wallet. PlutoWallet supports QR scanning, so one of your options is to put the access credentials uri inside the QR code. For example by using ZXing.Net.MAUI or other options.

Initialize Plutonication

                    
// Get the Plutonication account
Account account = await PlutonicationDAppClient.InitializeAsync(
    // Include your access credentials
    ac,

    // Optinally add extra behaviour on when the wallet successfully connects
    (string receivedPubkey) => {
        Console.WriteLine("Received public key: " + receivedPubkey);
    }
);
                 

Follow the comments.

InitializeAsync method finishes when the AccessCredentials are passed to the wallet and the wallet connects successfully to the Plutonication server. Do not get confused if your application gets stuck, this might be the reason.

Usage

                    
var substrateClient = new SubstrateClient(
    // Randomly chosen chain.
    // I generated the SubstrateClientExt according to this guide:
    // https://github.com/SubstrateGaming/Substrate.NET.API/wiki/Docs#scaffolding-with-substratenettoolchain
    new Uri("wss://ws.test.azero.dev"),
    ChargeTransactionPayment.Default()
);

// Do not forget to connect the SubstrateClient
await substrateClient.ConnectAsync();

var destinationAccountId = new AccountId32();
destinationAccountId.Create(Utils.GetPublicKeyFrom("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"));

var destinationMultiAddress = new EnumMultiAddress();
destinationMultiAddress.Create(0, destinationAccountId);

var amount = new BaseCom(1000000000000); // This is equivalent to 1 TZERO token (10^12 planks)

// Building the transfer Method
Method transfer = BalancesCalls.Transfer(destinationMultiAddress, amount);

// Make a Balances.Transfer call
await substrateClient.Author.SubmitExtrinsicAsync(
    transfer,
    account, // Request a signature from the Plutonication account
    ChargeTransactionPayment.Default(), // No tip
    64, // Lifetime. For details, refer to: https://polkadot.js.org/docs/api/FAQ/#how-long-do-transactions-live
    CancellationToken.None
);
                 

The following code showcases how you can make Balances.Transfer call on Aleph Zero Testnet chain that is signed by the account that connected through Plutonication.

Everything is explained by the comments.

Sample code on github

Wallet client

                    
// any account
Account alice = getAlice();

await PlutonicationWalletClient.InitializeAsync(
    // Your Access Credentials
    ac,

    // Account public address
    alice.Value,

    // Payload signing logic
    async (unCheckedExtrinsic, runtime) => {
        //
        // You can use the unCheckedExtrinsic and runtime to showcase the
        // info about the transaction to the user before signing it.
        //

        // Get the Extrinsic Payload and sign it
        Substrate.NetApi.Model.Extrinsics.Payload payload = unCheckedExtrinsic.GetPayload(runtime);
        unCheckedExtrinsic.AddPayloadSignature(await alice.SignPayloadAsync(payload));

        var signerResult = new SignerResult
        {
            // Id of the signature
            id = 1,
            signature = Utils.Bytes2HexString(
                // This 1 means the signature is using Sr25519
                new byte[1] { 1 }
                // The signature
                .Concat(unCheckedExtrinsic.Signature).ToArray()
            ).ToLower(),
        };

        // Send the payload signature to the dApp.
        await PlutonicationWalletClient.SendPayloadSignatureAsync(signerResult);
    },

    // Raw message signing logic
    async (raw) => {
        //
        // You can use the raw to show the message to the user before signing it.
        //

        if (raw.type != "bytes")
        {
            // Unsupported
            return;
        }

        byte[] rawMessageBytes = Utils.HexToByteArray(raw.data);

        var signerResult = new SignerResult
        {
            // Id of the signature
            id = 1,
            signature = Utils.Bytes2HexString(
                await alice.SignAsync(rawMessageBytes)
            ).ToLower(),
        };

        await PlutonicationWalletClient.SendRawSignatureAsync(signerResult);
    }
);

// Disconnect
await PlutonicationWalletClient.DisconnectAsync();
                 

If you are developing your own crypto wallet and you want to add Plutonication into your app, then you are at the right place.

By calling PlutonicationWalletClient.InitializeAsync with correct arguments, you will initialize the wallet client in the background. You do not have to do anything else.

Yes, It works like a magic!

PlutonicationWalletClient is a static class.

Sample wallet