Polkadot Facade Feedback
Opened this issue · 1 comments
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:
- 🤓 read: You had/wish to read something from the chain (most likely a pallet's storage / runtime-api), and you found it difficult.
- ✍️ write: You had/wish to compose a transaction to do something, and you found it difficult.
A few notes:
- 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.
- 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.
- 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.
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
, anderasStakersPaged
. - 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 }[] }>; }
- The big difference here is giving compatibility between the deprecated
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 themortalLength
,header
, andnonce
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[]; };