0

I've created test address in westend network. Topped up it using faucet. https://westend.subscan.io/account/5FpS4PkRzLmJZcwvJM6jxPU3N3481nbnTe6nzFwwQUVvu9LF?tab=transfer. In explorer I see 1WND balance, but if I try to retrive it using rpc func I receive wrong amount

package main

import (
    "encoding/hex"
    "fmt"
    gsrpc "github.com/centrifuge/go-substrate-rpc-client/v4"
    config2 "github.com/centrifuge/go-substrate-rpc-client/v4/config"
    "github.com/centrifuge/go-substrate-rpc-client/v4/types"
    "github.com/vedhavyas/go-subkey"
    "github.com/vedhavyas/go-subkey/sr25519"
)

func GetBalance(api *gsrpc.SubstrateAPI) {

    uri := balanceURI
    key, err := GetKey(uri)
    if err != nil {
        panic(err)
    }
    addr := PrintAddr("test balance addr", key)
    fmt.Println("addr = ", addr)
    public := key.Public()
    fmt.Println("public: ", "0x"+hex.EncodeToString(public))

    meta, err := api.RPC.State.GetMetadataLatest()
    if err != nil {
        panic(err)
    }
    storageKey, err := types.CreateStorageKey(
        meta, "System", "Account", public, nil)
    if err != nil {
        panic(err)
    }
    // Retrieve the initial balance
    var accountInfo types.AccountInfo
    ok, err := api.RPC.State.GetStorageLatest(storageKey, &accountInfo)
    if err != nil || !ok {
        panic(err)
    }
    fmt.Println(accountInfo)
    fmt.Println("Free balance: ", accountInfo.Data.Free)
    fmt.Println("FreeFrozen balance: ", accountInfo.Data.FreeFrozen)
    fmt.Println("MiscFrozen balance: ", accountInfo.Data.MiscFrozen)
    fmt.Println("Reserved balance: ", accountInfo.Data.Reserved)
}

func main() {
    config := config2.Default()
    config.RPCURL = WestEndUrl

    api, err := gsrpc.NewSubstrateAPI(config.RPCURL)
    if err != nil {
        panic(err)
    }
    fmt.Println(api)

    GetBalance(api)
}

func GetKey(uri string) (subkey.KeyPair, error) {
    scheme := sr25519.Scheme{}
    kr, err := subkey.DeriveKeyPair(scheme, uri)
    if err != nil {
        return nil, err
    }

    return kr, nil
}

func PrintAddr(caption string, key subkey.KeyPair) string {
    addr, err := key.SS58Address(42)
    if err != nil {
        panic(err)
    }

    fmt.Println(caption, addr)
    return addr
}

const WestEndUrl = "wss://westend-rpc.polkadot.io"
const balanceURI = "...//foo//42///password"

and the output:

GOROOT=/usr/local/go #gosetup
GOPATH=/home/andrew/go #gosetup
/usr/local/go/bin/go build -o /tmp/GoLand/___go_build_sample_westend_with_faucet sample/westend_with_faucet #gosetup
/tmp/GoLand/___go_build_sample_westend_with_faucet
2022/11/07 11:39:28 Connecting to wss://westend-rpc.polkadot.io...
&{0xc0000da580 0xc0001d2090}
test balance addr 5FpS4PkRzLmJZcwvJM6jxPU3N3481nbnTe6nzFwwQUVvu9LF
addr =  5FpS4PkRzLmJZcwvJM6jxPU3N3481nbnTe6nzFwwQUVvu9LF
public:  0xa60e515cdbf7e1426e9d708bc78ee0ed7d0f4c5c04951be09e37e70ad31a487c
{0 0 1 {4294967296000000000000 0 0 0}}
Free balance:  4294967296000000000000
FreeFrozen balance:  0
MiscFrozen balance:  0
Reserved balance:  0

amount is 4294967296000000000000 - it's not equal to 1WND

2 Answers 2

1

Looks like the library you are using is not up-to-date with the current Westend version. In particular - it decodes the response of System.account using the old definition of AccountInfo.

Notice that the printed structure contains three number values besides the nested structure with balances - 0 0 1. However, if you will take a look at the same query in the Polkadot.js apps UI, you will see that there are actually four of them:

{
  nonce: 0
  consumers: 0
  providers: 1
  sufficients: 0
  data: {
    free: 1,000,000,000,000
    reserved: 0
    miscFrozen: 0
    feeFrozen: 0
  }
}

So the library does not know about sufficients field and tries to decode the bytes of sufficients as being nested data structure, thus causing corruption

Worth to mention that addition of sufficients is rather old change - so if the library you are using is maintained - there should be already new version available that is compatible with abovementioned changes.

1

Maybe add more prints to check if is doing the proper calls.

I have tried the same using a basic script with PolkadotJS

const { ApiPromise, WsProvider } = require('@polkadot/api');

async function getBalance() {
  const wsProvider = new WsProvider('wss://westend-rpc.polkadot.io');
  const api = await ApiPromise.create({ provider: wsProvider });
  const chain = await api.rpc.system.chain();
  console.log(`----- Chain: ${chain} -----`);
  // The actual address that we will use
  const ADDR = '5FpS4PkRzLmJZcwvJM6jxPU3N3481nbnTe6nzFwwQUVvu9LF';
  // Retrieve the account balance & nonce via the system module
  const data = await api.query.system.account(ADDR);
  console.log(`Balance of the account ${ADDR} is: `);
  console.log(JSON.stringify(data));

 }

And the result is what you should have 1WND:

{"nonce":0,"consumers":0,"providers":1,"sufficients":0,"data":{"free":1000000000000,"reserved":0,"miscFrozen":0,"feeFrozen":0}}

Trying to manually query the RPC query state_getStorage of your account:

curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "state_getStorage", "params":["0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da95e0bd5326aa7e9fa72c036a33d96d381a60e515cdbf7e1426e9d708bc78ee0ed7d0f4c5c04951be09e37e70ad31a487c"]}' https://westend-rpc.polkadot.io

It returns you the same value too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.