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

Provide metadata for accounts so account fields can be read via anchor #1192

Closed
swaglord8 opened this issue Feb 20, 2023 · 7 comments
Closed
Labels
solana The Solana target

Comments

@swaglord8
Copy link

In all the Solana examples, view functions require a signer with funds simply to fetch data from an account. This works ok for tests but not when fetching from a browser using phantom as it gets disruptive

I think there should be more examples that show how one can use something like program.account.state.fetch(<account>) to get data from a program which I've seen used in anchor projects

@seanyoung seanyoung added the solana The Solana target label Feb 21, 2023
@seanyoung
Copy link
Contributor

Can you give a code example of this please?

I think the state stuff has been removed from anchor, see coral-xyz/anchor#2285 (this is post 0.26.0)

@swaglord8
Copy link
Author

@seanyoung
Sure. Here's an example using the flipper.sol example

import { AnchorProvider, Program } from '@project-serum/anchor'
import { useConnection, useWallet } from '@solana/wallet-adapter-react'
import { Keypair, PublicKey, SystemProgram, Transaction } from '@solana/web3.js'
import React, { useMemo } from 'react'
import IDL from '../../contract/build/flipper.json'
import ACCOUNTS from '../../contract/build/accounts.json'

export function Test() {
  const storage = useMemo(() => Keypair.generate(), [])
  const wallet = useWallet()
  const { connection } = useConnection()

  const provider = useMemo(() =>
    new AnchorProvider(connection, wallet!, { preflightCommitment: 'processed' })
  , [connection, wallet])

  const program = useMemo(() =>
    new Program(
      IDL as any,
      new PublicKey(ACCOUNTS.flipper),
      provider,
    )
  , [provider])

  const createAccount = async () => {
    // Create storage
    await provider.sendAndConfirm(
      new Transaction().add(
        SystemProgram.createAccount({
          fromPubkey: wallet.publicKey!,
          newAccountPubkey: storage.publicKey,
          lamports: await provider.connection.getMinimumBalanceForRentExemption(1024),
          space: 1024,
          programId: program.programId,
        }),
      )
      , [storage])
    // Instantiate contract
    await wallet.sendTransaction(
      await program.methods
        .new(true)
        .accounts({ dataAccount: storage.publicKey })
        .transaction()
      , provider.connection)
  }

  const fetchState = async () => {
    // Requires Phantom signature ---->
    const state = await program.methods
      .get()
      .accounts({ dataAccount: storage.publicKey })
      .view()
    console.log(state)
  }

  return (
    <>
      <button onClick={createAccount}>Init</button>
      <button onClick={fetchState}>Fetch state</button>
    </>
  )
}

@seanyoung
Copy link
Contributor

@swaglord8 I am afraid I am not following. Are you talking about:

    // Requires Phantom signature ---->
    const state = await program.methods
      .get()
      .accounts({ dataAccount: storage.publicKey })
      .view()
    console.log(state)

All this requires is the program and the storage.publicKey. I must be missing something, how is the wallet required?

@swaglord8
Copy link
Author

@seanyoung Yeah that's the line I'm talking about.

In other anchor react examples I've seen people use
const data = await program.account.<some account name>.fetch(storage.publicKey) to fetch data.

But the IDLs in those examples have contained an array of named accounts next to instructions, and I'm not sure how to replicate that in Solang nor seen any examples that have this

The anchor docs says:

The namespace provides handles to an [[AccountClient]] object for each account in the program.

Usage
program.account.<account-client>
Example
To fetch a Counter account from the above example,

const counter = await program.account.counter.fetch(address);
For the full API, see the [[AccountClient]] reference.

@seanyoung
Copy link
Contributor

@swaglord8 interesting I did not know that, we're also getting used to Anchor so let me see what I can find

@seanyoung
Copy link
Contributor

So the program.accounts.foo.fetch() interface uses metadata which describes the layout of the account, so it can be read directly from the account storage, and no BPF program code is executed (simulated or not).

Currently we do not provide this metadata. This should definitely be fixed; in the mean time, it is possible to use simulated calls to get the values from the contract, like you would on Ethereum - that's the way Solidity works right now.

@seanyoung seanyoung changed the title .view() require a signature Provide metadata for accounts so account fields can be read via anchor Mar 2, 2023
@seanyoung seanyoung added this to the Prepare for Solana Hackathon milestone Mar 2, 2023
@LucasSte
Copy link
Contributor

This is the same problem as in #541

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

No branches or pull requests

3 participants