diff --git a/schema.graphql b/schema.graphql index e8cc0bc..516ef1b 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1,33 +1,76 @@ # -# Main entities +# Provides information about an Ethereum account # - type Account @entity { + " Equals to: " id: ID! + + " Account address " address: Bytes! + + " Token balances that this account holds " + balances: [AccountBalance!]! @derivedFrom(field: "account") } +# +# Current token balance of a particular Ethereum account +# type AccountBalance @entity { + " Equals to: -" id: ID! + + " Account address " account: Account! + + " Token address " token: Token! + + " Current account balance " amount: BigDecimal! + + " Block number in which the balance was last modified " + block: BigInt + + " Last modified timestamp in seconds " + modified: BigInt + + " Hash of the last transaction that modified the balance " + transaction: Bytes } -# This entity is used to provide information about evolution of account balances -type AccountBalanceLog @entity { +# +# Token balance of a particular Ethereum account in a certain timestamp. This entity is used to +# provide information about evolution of account balances +# +type AccountBalanceSnapshot @entity { + " Equals to: --" id: ID! + + " Account address " account: Account! + + " Token addess " token: Token! + + " Account balance " amount: BigDecimal! + # TODO: Add description and check if could be non-optional event: TokenEvent + " Block number " block: BigInt! - transaction: Bytes! + + " Timestamp in seconds " timestamp: BigInt! + + " Transaction hash " + transaction: Bytes! } +# +# Provides information about an ERC20 token +# type Token @entity { id: ID! @@ -68,10 +111,9 @@ type Token @entity { } # -# Events +# Token events # - -interface TokenEvent @entity { +interface TokenEvent { id: ID! token: Token! amount: BigDecimal! diff --git a/src/mappings/account.ts b/src/mappings/account.ts index 45f8874..8dd4271 100644 --- a/src/mappings/account.ts +++ b/src/mappings/account.ts @@ -1,35 +1,22 @@ import { BigDecimal, BigInt, Bytes, EthereumEvent } from '@graphprotocol/graph-ts' -import { Account, AccountBalance, AccountBalanceLog, Token } from '../../generated/schema' - -export function createAccountBalance(balance: AccountBalance, event: EthereumEvent): AccountBalanceLog { - let logEntity = new AccountBalanceLog(event.transaction.hash.toHex() + '-' + event.logIndex.toString()) - logEntity.account = balance.account - logEntity.token = balance.token - logEntity.amount = balance.amount - - logEntity.block = event.block.number - logEntity.transaction = event.transaction.hash - logEntity.timestamp = event.block.timestamp - - return logEntity -} +import { Account, AccountBalance, AccountBalanceSnapshot, Token } from '../../generated/schema' export function getOrCreateAccount(accountAddress: Bytes): Account { let accountId = accountAddress.toHex() - let existingEntity = Account.load(accountId) + let existingAccount = Account.load(accountId) - if (existingEntity != null) { - return existingEntity as Account + if (existingAccount != null) { + return existingAccount as Account } - let newEntity = new Account(accountId) - newEntity.address = accountAddress + let newAccount = new Account(accountId) + newAccount.address = accountAddress - return newEntity + return newAccount } -export function getOrCreateAccountBalance(account: Account, token: Token): AccountBalance { +function getOrCreateAccountBalance(account: Account, token: Token): AccountBalance { let balanceId = account.id + '-' + token.id let previousBalance = AccountBalance.load(balanceId) @@ -58,3 +45,18 @@ export function decreaseAccountBalance(account: Account, token: Token, amount: B return balance } + +export function saveAccountBalanceSnapshot(balance: AccountBalance, eventId: string, event: EthereumEvent): void { + let snapshot = new AccountBalanceSnapshot(balance.id + '-' + event.block.timestamp.toString()) + snapshot.account = balance.account + snapshot.token = balance.token + snapshot.amount = balance.amount + + snapshot.block = event.block.number + snapshot.transaction = event.transaction.hash + snapshot.timestamp = event.block.timestamp + + snapshot.event = eventId + + snapshot.save() +} diff --git a/src/mappings/token.ts b/src/mappings/token.ts index d0a4121..fad6467 100644 --- a/src/mappings/token.ts +++ b/src/mappings/token.ts @@ -1,12 +1,17 @@ -import { BigInt, BigDecimal, Bytes, EthereumEvent, log } from '@graphprotocol/graph-ts' +import { BigInt, BigDecimal, Bytes, EthereumEvent } from '@graphprotocol/graph-ts' import { Transfer } from '../../generated/TokenRegistry/templates/StandardToken/ERC20' import { Burn } from '../../generated/TokenRegistry/templates/BurnableToken/Burnable' import { Mint } from '../../generated/TokenRegistry/templates/MintableToken/Mintable' -import { Account, BurnEvent, MintEvent, Token, TransferEvent } from '../../generated/schema' +import { BurnEvent, MintEvent, Token, TransferEvent } from '../../generated/schema' -import { getOrCreateAccount, decreaseAccountBalance, increaseAccountBalance, createAccountBalance } from './account' +import { + decreaseAccountBalance, + getOrCreateAccount, + increaseAccountBalance, + saveAccountBalanceSnapshot +} from './account' const GENESIS_ADDRESS = '0x0000000000000000000000000000000000000000' @@ -43,30 +48,32 @@ export function handleTransfer(event: Transfer): void { // Updates balances of accounts if (isTransfer || isBurn) { let sourceAccount = getOrCreateAccount(event.params.from) + let accountBalance = decreaseAccountBalance(sourceAccount, token as Token, amount) + accountBalance.block = event.block.number + accountBalance.modified = event.block.timestamp + accountBalance.transaction = event.transaction.hash sourceAccount.save() accountBalance.save() - // To provide information about evolution of account balance - let accountBalanceLog = createAccountBalance(accountBalance, event) - accountBalanceLog.event = eventEntityId - - accountBalanceLog.save() + // To provide information about evolution of account balances + saveAccountBalanceSnapshot(accountBalance, eventEntityId, event) } if (isTransfer || isMint) { let destinationAccount = getOrCreateAccount(event.params.to) + let accountBalance = increaseAccountBalance(destinationAccount, token as Token, amount) + accountBalance.block = event.block.number + accountBalance.modified = event.block.timestamp + accountBalance.transaction = event.transaction.hash destinationAccount.save() accountBalance.save() - // To provide information about evolution of account balance - let accountBalanceLog = createAccountBalance(accountBalance, event) - accountBalanceLog.event = eventEntityId - - accountBalanceLog.save() + // To provide information about evolution of account balances + saveAccountBalanceSnapshot(accountBalance, eventEntityId, event) } } } @@ -83,16 +90,17 @@ export function handleBurn(event: Burn): void { // Update source account balance let account = getOrCreateAccount(event.params.burner) - account.save() let accountBalance = decreaseAccountBalance(account, token as Token, amount) + accountBalance.block = event.block.number + accountBalance.modified = event.block.timestamp + accountBalance.transaction = event.transaction.hash + + account.save() accountBalance.save() - // To provide information about evolution of account balance - let accountBalanceLog = createAccountBalance(accountBalance, event) - accountBalanceLog.event = eventEntity.id - - accountBalanceLog.save() + // To provide information about evolution of account balances + saveAccountBalanceSnapshot(accountBalance, eventEntity.id, event) } } @@ -107,17 +115,18 @@ export function handleMint(event: Mint): void { eventEntity.save() // Update destination account balance - let account: Account = getOrCreateAccount(event.params.to) - account.save() + let account = getOrCreateAccount(event.params.to) let accountBalance = increaseAccountBalance(account, token as Token, amount) + accountBalance.block = event.block.number + accountBalance.modified = event.block.timestamp + accountBalance.transaction = event.transaction.hash + + account.save() accountBalance.save() - // To provide information about evolution of account balance - let accountBalanceLog = createAccountBalance(accountBalance, event) - accountBalanceLog.event = eventEntity.id - - accountBalanceLog.save() + // To provide information about evolution of account balances + saveAccountBalanceSnapshot(accountBalance, eventEntity.id, event) } }