Propositon pour obtenir facilement le solde d'un compte sans indexeur

Merge request GitLab associée à la proposition: Draft: Resolve "Create a runtime API UniversalDividendApi_account_balances to retrieve total and transferable account balances" (!328) · Merge requests · nodes / rust / Duniter v2S · GitLab

Contexte et problème

Aujourd’hui, la plupart des wallets et applications tierces s’appuient sur un indexeur (par exemple un service GraphQL) pour récupérer la balance d’un compte.

  • Pour un utilisateur, savoir « combien de Ğ1 j’ai » est critique : cela doit fonctionner même si l’indexeur est hors-service ou en retard.
  • En l’absence d’indexeur, certaines applications peuvent ne pas permettre d’initier un transfert, car elles imposent de connaître d’abord le solde transférable. Or l’utilisateur doit pouvoir initier un transfert sans indexeur.

Proposition

Ajouter une runtime API nommée UniversalDividendApi_account_balances qui renvoie, pour un AccountId, les champs suivants :

{
  /// Total des fonds dont l’utilisateur est propriétaire
  total: number,

  /// Fonds réellement transférables (inclut les DUs non réclamés, mais exclut le « dépôt d’existence » et les fonds réservés)
  transferable: number,

  /// Montant total des DUs non-réclamés
  unclaim_uds: number
}

Pour rappel, toutes les runtime APIs sont des fonctions « read-only » appelables via RPC avec la méthode state_call(apiName, params). La convention substrate pour le nom des runtime API est NameApi_function_name.

Comme leur nom l’indique, les runtime APIs peuvent être ajoutées ou modifiées uniquement par un changement de runtime ; il n’est pas nécessaire de livrer un nouveau binaire de duniter-v2s.

Exemples d’appel avec curl, Polkadot.js et PAPI

:warning: Ces exemples ne fonctionne pas sur la GDev actuelle car le runtime 900 n’inclus pas la MR !328. Pour tester il vous faut une chaine locale avec un runtime qui inclus cette MR.

Curl

RPC_URL="http://127.0.0.1:9933"
HEX_ACCOUNT="0x0123…ef" # Clé publique paddée à 32 octets et encodée en hexadécimal

curl -X POST $RPC_URL \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc":"2.0",
    "id":1,
    "method":"state_call",
    "params":[
      "UniversalDividendApi_account_balances",
      "'"${HEX_ACCOUNT}"'"
    ]
  }'

Polkadot.js

import { ApiPromise, WsProvider } from '@polkadot/api';

async function getBalances(ss58) {
  const api = await ApiPromise.create({ provider: new WsProvider('ws://127.0.0.1:9944') });
  const hex = api.createType('AccountId', ss58).toHex();
  const raw = await api.rpc.state.call('UniversalDividendApi_account_balances', hex);
  const [ total, transferable, unclaimUds ] = api
    .createType('(u64,u64,u64)', raw)
    .toJSON();
  console.log({ total, transferable, unclaimUds });
}

getBalances('5F3sa2TJAWMqDhXG6jhV4N8ko9E…');

PAPI

import { createClient } from 'polkadot-api';
import { getWsProvider } from 'polkadot-api/ws-provider/web';

async function getBalances(ss58: string) {
  const client = createClient(getWsProvider('ws://127.0.0.1:9944'));
  const api = client.getTypedApi(gdev);
  const { total, transferable, unclaimAmount } =
    await api.apis.UniversalDividendApi.accountBalances(ss58);
  console.log(total.toString(), transferable.toString(), unclaimAmount.toString());
}

getBalances('5F3sa2TJAWMqDhXG6jhV4N8ko9E…');

Si cela vous donne des idées d’autres runtimes API qui serait utiles pour les wallet et applications, merci de créer un nouveau sujet par runtime API proposée.

6 Likes

Les wallets devraient quand même l’autoriser, en utilisant transfer_keep_alive.

2 Likes

Le problème, c’est que si un wallet soumet un transfer_keep_alive en essayant de transférer plus que le solde transférable, la transaction sera quand même incluse en blockchain et consommera malgré tout les quotas de l’utilisateur (voire ponctionnera des frais de transaction si aucun quota gratuit n’est disponible).

En effet, du point de vue de Substrate, la transaction en elle-même est parfaitement valide, même si l’exécution du runtime call transfer_keep_alive retourne une erreur.

C’est pourquoi les wallets doivent connaître leur solde transférable avant d’envoyer un transfer.

3 Likes