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

feat: solana balances #19

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

feat: solana balances #19

wants to merge 3 commits into from

Conversation

ricardocr987
Copy link
Contributor

I have used the discoverAccounts implementation, which is prepared to set an interval to run a job, the holders snapshot is taken every hour.

The balance query, if Solana is requested, returns the last snapshot, but it is also possible to query other snapshots taken giving a timestamp, will return last snapshot of that timestamp.

Copy link
Member

@MHHukiewitz MHHukiewitz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good in general, but I think having 1 hour of discovering new ALEPH holders will be too frustrating to new users wanting to stake tokens.

Some alternatives I could see, prerrably the first ones:

  • Find out when people create an $ALEPH ATA instantly and create a latest snapshot from it.
  • Force refresh all $ALEPH holders when calling the balances endpoint (or add a parameter to request the latest balances)

Comment on lines -32 to +33
export const ERC20Balance = new GraphQLObjectType({
name: 'ERC20Balance',
export const Balance = new GraphQLObjectType({
name: 'Balance',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be still a ERC20Balance, as we have a Solana specific implementation down below

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

balance query also can return solana balances from snapshot db

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see now where the problem in this discussion lies.

What you can do is make Balance a union of two types, ERC20Balance and SolanaBalance:

const erc20BalanceFields = {
  account: { type: new GraphQLNonNull(GraphQLString) },
  balance: { type: new GraphQLNonNull(GraphQLBigNumber) },
  balanceNum: { type: GraphQLFloat },
}

const solanaBalanceFields = {
  ...erc20BalanceFields,
  tokenAccount: { type: new GraphQLNonNull(GraphQLString) },
}

export const ERC20Balance = new GraphQLObjectType({
  name: 'ERC20Balance',
  fields: erc20BalanceFields,
})

export const SolanaBalance = new GraphQLObjectType({
  name: 'SolanaBalance',
  fields: solanaBalanceFields,
})

export const Balance = new GraphQLUnionType({
  name: 'Balance',
  types: [ ERC20Balance, SolanaBalance],
});

This will allow you to keep all the relevant info for Solana-related balances, while not having to deal with undefined values for ERC20Balances. This style also comes in handy later, when you might want to filter balances based on which type they are.

Comment on lines 46 to 47
account: { type: new GraphQLNonNull(GraphQLString) },
owner: { type: new GraphQLNonNull(GraphQLString) },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comparing this to the previous ERC20Balance, the account fields mean two different things:

  • For ERC20 it is the owner account
  • For Solana is is the ATA

For clarification I'd prefer if the owner account stays the account and instead we call the ATA the tokenAccount

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay i can change that, then balances query should return tokenAccount or owner? it seems more straightforward to return the tokenAccount as this is where the tokens are stored. I can implement a query to return token account data also.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tokenAccount is an implementation detail that is not relevant to (most) users. Provide the information, but don't make it the primary identifier. The owner address is much more relevant to most usecases.

},
})

export const types = [TransferEvent, Balance, Snapshot]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solana types are not being exported in this list, is this intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Snapshot is the 'solana type', balances query also returns solana balances data

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels a bit off to me... Are ERC20 balances not capable of snapshots? Why even collect snapshots then, if we could just try to index the current balance at any time?

@@ -49,7 +49,7 @@ const mapValueFn = async (value: any) => {

export function createBalanceDAL(path: string): BalanceStorage {
return new EntityStorage<Balance>({
name: 'erc20_balance',
name: 'balance',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we are storing Balance (previously ERC20Balance) in this database. What about Solana balances and their additional field then? Are they not stored?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The snapshot taken is stored on the snapshot dal

if (!accountBalance) {
const balance = blockchainTotalSupply[blockchain].toString('hex')
await this.balanceDAL.save({ blockchain, account: deployer, balance })
if (!meta) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not on meta?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Token contracts are indexed without any meta, inside the condition is executed code related to token contracts

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to comment on that. Had no idea.

Comment on lines 57 to 58
account: string
owner: string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, the owner is more similar to the account field of the ERC20Balance

Comment on lines 29 to 30
// note: Snapshot interval is set to 1 hour
protected discoveryInterval = 1000 * 60 * 60,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels way too long in my opinion. Is there no way to instantly recognize newly created ATAs? When users add funds to their wallet and want to stake, they expect our indexers to instantly recognize the added tokens.

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

Successfully merging this pull request may close these issues.

2 participants