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

Polkadot Facade Feedback #11021

Open
kianenigma opened this issue Oct 18, 2024 · 1 comment
Open

Polkadot Facade Feedback #11021

kianenigma opened this issue Oct 18, 2024 · 1 comment

Comments

@kianenigma
Copy link

We are working towards building better APIs to simplify the interacting with "Polkadot Network".

What do we mean here by Polkadot Network? Foremost Polkadot Relay Chain and System Chains (everything DOT related), and then other Parachains.

In a few months (and after gathering feedback via such issues), more details of this project will be shared. To give it a name for now, we are calling it "Polkadot Facade".

The aim of this issue is to learn about the instances where you had to interact with Polkadot Network (as defined above), and you found it difficult. This interaction can be in any form, but to help give you a mental model, I can categorize it as such:

  1. 🤓 read: You had/wish to read something from the chain (most likely a pallet's storage / runtime-api), and you found it difficult.
  2. ✍️ write: You had/wish to compose a transaction to do something, and you found it difficult.

A few notes:

  1. I used the "had/wish" intentionally: I would like to hear both about scenarios that you had to do something, and they were hard, and those that you couldn't even figure out how to do because it was too hard.
  2. You can focus both on single-network interactions, and multi-network (involving XCM) interactions. That being said, we will likely first consider single-network cases.
  3. When it comes to reading, don't limit yourself to what can be read from the state of a certain block, historical queries also count.

Please feel free to reach out to me on Matrix (@kianenigma:parity.io) if need be.

@TarikGul
Copy link
Member

TarikGul commented Nov 7, 2024

Read

Note: Any typing examples below will use JS primitive types, and are just examples of aggregated data as a result. These are there as base filler values, and will obviously be interpreted differently on chain depending on the rust types used.

Staking

Staking is probably one of the most obvious pallets that will benefit from Facade. It will definitely be tough to introduce historical support as well for state that was generated with pallet staking versions below v14, but I think if that is completely abstracted from the user it will introduce a really smooth experience.

Generally getting all the information aggregated for staking can be difficult - plus shifting code around to ensure compatibility with changes becomes really hard in already established systems.

  • Staking rewards (Single-network): for either nominators or validators.

    • There is a lot of ways to format the data but overall I think it's best to read it based on an account, and the following 82 eras that are saved in storage. Below would be some useful data to have in a read described above:
    interface Result {
        era: string;
        eraReward: string;
        isClaimed: boolean;
        isValidator: boolean;
        nominating: string[];
        validators: string[];
    }
  • Staking era exposures (Single-network): A good reference for the logic can be found here.

    • The big difference here is giving compatibility between the deprecated erasStakersClipped, and erasStakersPaged.
    • An example output would look like:
    interface Result {
        era: string;
        nominators: Record<string, {
          validatorId: string;
          validatorIndex: number;
        }[]>;
        validators: Record<string, {
          pageTotal: string;
          others: { who: string; value: number }[]
        }>;
    }

Signing

Generally, retrieving signing info takes multiple queries and some small calculations. Aggregating it into one would bring a little more organization to this.

  • Signing info (Single-network): It is gathered in PJS by using api.derive.tx.signingInfo - this would be great if it was abstracted into a single facade function. This aggregates the mortalLength, header, and nonce based on an account address.
    interface Result {
      header: string | null;
      mortalLength: number;
      nonce: number;
    }
    

Balancesz

The way data is shaped and interpreted around Balances has changed a lot over the years. It's always a challenge keeping up, and ensuring the data is correctly calculated and aggregated.

  • All Balances including assets(Including assets: Multi-network): It would be useful to have a way to retrieve all balances and assets under a single account.

  • All Balances (Single-network): The type below will give an example of what this would look like. This would be very valuable for historical compatibility. On Kusama it would be a bit tricky to get it to work all the way back to genesis but would be incredible useful for auditing, indexing, etc.

    interface Result {
      /**
       * max(0, free - locked)
       */
      availableBalance: string;
      lockedBalance: string;
      lockedBreakdown: {
        id: string;
        amount: string;
        reasons: PalletBalancesReasons;
      }[];
      /**
       * maybeEd = if frozen > 0 || reserve > 0 then 0 else extensionDeposit
       * free - max(maybeEd, frozen - reserve)
       */
      transferable: string;
      verstingLocked: string;
      frameSystemAccountInfo?: {
        frozen: string;
        flags: string;
      }
      freeBalance: string;
      frozenFee: string;
      frozenMisc: string;
      reservedBalance: string;
      votingBalance: string;
    }

Session

Generally, it's hard reading and or understanding the complex consensus pallets. Therefore, smaller facade functions that can aggregate the below could make a single source of truth for users easier to understand. This idea here can also be extended to other consensus pallets.

  • Session Progress (Single-network): This could include the simple calculations of the era progress and session progress for Babe consensus:

    interface Result {
      eraProgress: string; // BlockNumber
      sessionProgress: string; // BlockNumber
    }

    I believe the calculations are as follows:
    sessionProgress =currentSlot - ((epochIndex * epochDuration) + genesisSlot)
    eraProgress = (currentIndex - sessionIndex) * sessionLength + sessionProgress

    I good ref: https://github.com/polkadot-js/api/tree/master/packages/api-derive/src/session

Proposals (Treasury and Council)

Currently one needs to query both the council and treasury for proposals. It would be a bit easier to combine each in a facade function.

  • Aggregate all active and approved treasury proposals (Single-network): This would also include all residual info. This would also include Council proposals.
    interface TreasuryProposal {
      council: {
        hash:P string;
        proposal: Proposal;
        votes: Votes;
      }[],
      id: string;
      proposal: TreasuryProposal; 
    }
    
    interface Result {
      approvals: TreasuryProposal[];
      proposalCount: string;
      proposals: TreasuryProposal[];
    }

Democracy

This is super useful for PJS Apps. I don't have much experience with the Preimage and Referendum logic, but it has come in handy for users, and are quite active pages.

  • preimages (Single-network): Aggregating all preimage info.

    interface Result {
      balance: string;
      proposal: string | Call;
      proposalHash: string;
      proposalLength: string;
      proposer: string; // Address
      at: string; // BlockNumber
    }
  • Referedums (Single-network): Aggregating all referendum info. Can use the Preimage facade underneath for the image info. For reference: https://github.com/polkadot-js/api/tree/master/packages/api-derive/src/democracy

    interface ResultReferendumVote {
      accountId: string;
      balance: string;
      isDelegating: boolean;
      vote: Vote;
    }
    
    interface ResultReferendum {
      index: string; // ReferendumIndex
      image?: {
       balance: string;
       proposal: string | Call;
       proposalHash: string;
       proposalLength: string;
       proposer: string; // Address
       at: string; // BlockNumber
     };
     imageHash: string;
     status: ReferendumStatus;
     allAye: ResultReferendumVote[];
     allNay: ResultReferendumVote[];
     voteCount: number;
     voteCountAye: number;
     voteCountNay: number;
     votedAye: number;
     votedNay: number;
     votedTotal: number;
     isPassing: boolean;
     votes: ResultReferendumVote[];
    };

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants