diff --git a/subgraphs/protocol-reserve/README.md b/subgraphs/protocol-reserve/README.md new file mode 100644 index 00000000..450c5040 --- /dev/null +++ b/subgraphs/protocol-reserve/README.md @@ -0,0 +1,3 @@ +# Protocol Reserve Subgraph + +This subgraph indexes events for the Venus Protocol Reserve and related contracts such as the Token Converters diff --git a/subgraphs/protocol-reserve/config/index.ts b/subgraphs/protocol-reserve/config/index.ts new file mode 100644 index 00000000..0d876a00 --- /dev/null +++ b/subgraphs/protocol-reserve/config/index.ts @@ -0,0 +1,66 @@ +import mainnetDeployments from '@venusprotocol/protocol-reserve/deployments/bscmainnet_addresses.json'; +import chapelDeployments from '@venusprotocol/protocol-reserve/deployments/bsctestnet_addresses.json'; +import fs from 'fs'; +import Mustache from 'mustache'; + +export const getNetwork = () => { + const supportedNetworks = ['chapel', 'bsc', 'docker'] as const; + const network = process.env.NETWORK; + // @ts-expect-error network env var is unknown here + if (!supportedNetworks.includes(network)) { + throw new Error(`NETWORK env var must be set to one of ${supportedNetworks}`); + } + return network as (typeof supportedNetworks)[number]; +}; + +const main = () => { + const network = getNetwork(); + const config = { + docker: { + network: 'hardhat', + converterNetworkAddress: '0x0000000000000000000000000000000000000000', + btcbPrimeConverterAddress: '0x0000000000000000000000000000000000000000', + ethPrimeConverterAddress: '0x0000000000000000000000000000000000000000', + riskFundConverterAddress: '0x0000000000000000000000000000000000000000', + usdcPrimeConverterAddress: '0x0000000000000000000000000000000000000000', + usdtPrimeConverterAddress: '0x0000000000000000000000000000000000000000', + xvsVaultConverterAddress: '0x0000000000000000000000000000000000000000', + riskFundAddress: '0x0000000000000000000000000000000000000000', + startBlock: 0, + }, + chapel: { + network: 'chapel', + converterNetworkAddress: chapelDeployments.addresses.ConverterNetwork, + btcbPrimeConverterAddress: chapelDeployments.addresses.BTCBPrimeConverter, + ethPrimeConverterAddress: chapelDeployments.addresses.ETHPrimeConverter, + riskFundConverterAddress: chapelDeployments.addresses.RiskFundConverter, + usdcPrimeConverterAddress: chapelDeployments.addresses.USDCPrimeConverter, + usdtPrimeConverterAddress: chapelDeployments.addresses.USDTPrimeConverter, + xvsVaultConverterAddress: chapelDeployments.addresses.XVSVaultConverter, + riskFundAddress: chapelDeployments.addresses.RiskFundV2, + startBlock: '36750497', + }, + bsc: { + network: 'bsc', + converterNetworkAddress: mainnetDeployments.addresses.ConverterNetwork, + btcbPrimeConverterAddress: mainnetDeployments.addresses.BTCBPrimeConverter, + ethPrimeConverterAddress: mainnetDeployments.addresses.ETHPrimeConverter, + riskFundConverterAddress: mainnetDeployments.addresses.RiskFundConverter, + usdcPrimeConverterAddress: mainnetDeployments.addresses.USDCPrimeConverter, + usdtPrimeConverterAddress: mainnetDeployments.addresses.USDTPrimeConverter, + xvsVaultConverterAddress: mainnetDeployments.addresses.XVSVaultConverter, + riskFundAddress: mainnetDeployments.addresses.RiskFundV2, + startBlock: '32659400', + }, + }; + + const yamlTemplate = fs.readFileSync('template.yaml', 'utf8'); + const yamlOutput = Mustache.render(yamlTemplate, config[network]); + fs.writeFileSync('subgraph.yaml', yamlOutput); + + const configTemplate = fs.readFileSync('src/constants/config-template', 'utf8'); + const tsOutput = Mustache.render(configTemplate, config[network]); + fs.writeFileSync('src/constants/config.ts', tsOutput); +}; + +main(); diff --git a/subgraphs/protocol-reserve/matchstick.yaml b/subgraphs/protocol-reserve/matchstick.yaml new file mode 100644 index 00000000..772ec96c --- /dev/null +++ b/subgraphs/protocol-reserve/matchstick.yaml @@ -0,0 +1 @@ +libsFolder: ../../node_modules/ diff --git a/subgraphs/protocol-reserve/package.json b/subgraphs/protocol-reserve/package.json new file mode 100644 index 00000000..6ea198ee --- /dev/null +++ b/subgraphs/protocol-reserve/package.json @@ -0,0 +1,34 @@ +{ + "name": "protocol-reserve-subgraph", + "version": "0.0.0", + "license": "MIT", + "repository": { + "url": "https://github.com/VenusProtocol/subgraphs", + "directory": "subgraphs/isolated-pools" + }, + "files": [ + "generated" + ], + "scripts": { + "codegen": "npx graph codegen", + "create:docker": "npx graph create venusprotocol/venus-protocol-reserve --node http://graph-node:8020/", + "build:docker": "npx graph build --ipfs http://ipfs:5001", + "build:bsc": "graph build --ipfs https://api.thegraph.com/ipfs/ ", + "deploy:integration": "graph deploy venusprotocol/venus-protocol-reserve --ipfs http://localhost:5001 --node http://127.0.0.1:8020/", + "deploy:docker": "yarn prepare:docker && npx graph deploy venusprotocol/venus-protocol-reserve --ipfs http://ipfs:5001 --node http://graph-node:8020/ --version-label ci", + "deploy:chapel": "yarn prepare:chapel && graph deploy venusprotocol/venus-protocol-reserve-chapel --ipfs https://api.thegraph.com/ipfs/ --node https://api.thegraph.com/deploy/", + "deploy:bsc": "yarn prepare:bsc && graph deploy venusprotocol/venus-protocol-reserve --ipfs https://api.thegraph.com/ipfs/ --node https://api.thegraph.com/deploy/", + "prepare:docker": "NETWORK=docker npx ts-node config/index.ts", + "prepare:chapel": "NETWORK=chapel npx ts-node config/index.ts", + "prepare:bsc": "NETWORK=bsc npx ts-node config/index.ts", + "generate-subgraph-types": "rm -rf /subgraph-client/.graphclient && npx graphclient build --dir ./subgraph-client", + "pretty": "prettier —-write '**/*.ts'", + "test": "yarn prepare:docker && graph test", + "test:integration": "npx hardhat test tests/integration/index.ts --network localhost" + }, + "devDependencies": { + "apollo-fetch": "^0.7.0", + "urql": "^3.0.3", + "venus-subgraph-utils": "0.0.0" + } +} diff --git a/subgraphs/protocol-reserve/schema.graphql b/subgraphs/protocol-reserve/schema.graphql new file mode 100644 index 00000000..c91b0700 --- /dev/null +++ b/subgraphs/protocol-reserve/schema.graphql @@ -0,0 +1,38 @@ +enum ConversionAccessibility { + NONE + ALL + ONLY_FOR_CONVERTERS + ONLY_FOR_USERS +} + +""" +Converter Network entity +""" +type ConverterNetwork @entity { + id: ID! + tokenConverters: [TokenConverter!]! @derivedFrom(field: "converterNetwork") +} + +""" +Token Converter entity +""" +type TokenConverter @entity { + id: ID! + converterNetwork: ConverterNetwork + destinationAddress: Bytes! + baseAsset: Bytes! + configs: [TokenConverterConfig!]! @derivedFrom(field: "tokenConverter") + paused: Boolean! +} + +""" +Token Converter Config +""" +type TokenConverterConfig @entity { + id: ID! + tokenConverter: TokenConverter! + tokenAddressIn: Bytes! + tokenAddressOut: Bytes! + incentive: BigInt! + access: ConversionAccessibility! +} diff --git a/subgraphs/protocol-reserve/src/constants/addresses.ts b/subgraphs/protocol-reserve/src/constants/addresses.ts new file mode 100644 index 00000000..a6b0dca4 --- /dev/null +++ b/subgraphs/protocol-reserve/src/constants/addresses.ts @@ -0,0 +1,12 @@ +import { Address } from '@graphprotocol/graph-ts'; + +import { + converterNetworkAddress as converterNetworkAddressString, + riskFundAddress as riskFundAddressString, + riskFundConverterAddress as riskFundConverterAddressString, +} from './config'; + +export const converterNetworkAddress = Address.fromString(converterNetworkAddressString); +export const riskFundConverterAddress = Address.fromString(riskFundConverterAddressString); +export const riskFundAddress = Address.fromString(riskFundAddressString); +export const nullAddress = Address.fromString('0x0000000000000000000000000000000000000000'); diff --git a/subgraphs/protocol-reserve/src/constants/config-template b/subgraphs/protocol-reserve/src/constants/config-template new file mode 100644 index 00000000..d0a420ce --- /dev/null +++ b/subgraphs/protocol-reserve/src/constants/config-template @@ -0,0 +1,6 @@ +// Use yarn prepare commands to generate config typescript file per env + +export const converterNetworkAddress = '{{ converterNetworkAddress }}'; +export const riskFundConverterAddress = '{{ riskFundConverterAddress }}'; +export const riskFundAddress = '{{ riskFundAddress }}'; + diff --git a/subgraphs/protocol-reserve/src/constants/index.ts b/subgraphs/protocol-reserve/src/constants/index.ts new file mode 100644 index 00000000..a050924a --- /dev/null +++ b/subgraphs/protocol-reserve/src/constants/index.ts @@ -0,0 +1,12 @@ +import { BigDecimal, BigInt } from '@graphprotocol/graph-ts'; + +export const NOT_AVAILABLE_BIG_INT = BigInt.fromString('-1'); +export const NOT_AVAILABLE_BIG_DECIMAL = BigDecimal.fromString('-1'); + +export const zeroBigDecimal = BigDecimal.fromString('0'); +export const zeroBigInt32 = BigInt.fromString('0'); +export const oneBigInt = BigInt.fromString('1'); + +export const mantissaFactor = 18; + +export const ConversionAccessibility = ['NONE', 'ALL', 'ONLY_FOR_CONVERTERS', 'ONLY_FOR_USERS']; diff --git a/subgraphs/protocol-reserve/src/mappings/converterNetwork.ts b/subgraphs/protocol-reserve/src/mappings/converterNetwork.ts new file mode 100644 index 00000000..785207c5 --- /dev/null +++ b/subgraphs/protocol-reserve/src/mappings/converterNetwork.ts @@ -0,0 +1,21 @@ +import { + ConverterAdded, + ConverterRemoved, +} from '../../generated/ConverterNetwork/ConverterNetwork'; +import { deleteTokenConvertor } from '../operations/delete'; +import { getOrCreateConverterNetwork, getOrCreateTokenConvertor } from '../operations/getOrCreate'; +import { getConverterNetworkId } from '../utilities/ids'; + +export function handleConverterAdded(event: ConverterAdded): void { + getOrCreateConverterNetwork(event.address); + const tokenConverter = getOrCreateTokenConvertor(event.params.converter); + tokenConverter.converterNetwork = getConverterNetworkId(event.address); + tokenConverter.save(); +} + +export function handleConverterRemoved(event: ConverterRemoved): void { + deleteTokenConvertor(event.params.converter); + const tokenConverter = getOrCreateTokenConvertor(event.params.converter); + tokenConverter.converterNetwork = null; + tokenConverter.save(); +} diff --git a/subgraphs/protocol-reserve/src/mappings/tokenConverter.ts b/subgraphs/protocol-reserve/src/mappings/tokenConverter.ts new file mode 100644 index 00000000..5aedcc4a --- /dev/null +++ b/subgraphs/protocol-reserve/src/mappings/tokenConverter.ts @@ -0,0 +1,46 @@ +import { + BaseAssetUpdated, + ConversionConfigUpdated, + ConversionPaused, + ConversionResumed, + ConverterNetworkAddressUpdated, + DestinationAddressUpdated, +} from '../../generated/BTCBPrimeConverter/TokenConverter'; +import { getOrCreateTokenConvertor } from '../operations/getOrCreate'; +import { updateOrCreateTokenConverterConfig } from '../operations/updateOrCreate'; +import { getConverterNetworkId } from '../utilities/ids'; + +export function handleConversionConfigUpdated(event: ConversionConfigUpdated): void { + getOrCreateTokenConvertor(event.address); + updateOrCreateTokenConverterConfig(event.address, event.params); +} + +export function handleConversionPaused(event: ConversionPaused): void { + const tokenConverter = getOrCreateTokenConvertor(event.address); + tokenConverter.paused = true; + tokenConverter.save(); +} + +export function handleConversionResumed(event: ConversionResumed): void { + const tokenConverter = getOrCreateTokenConvertor(event.address); + tokenConverter.paused = false; + tokenConverter.save(); +} + +export function handleConverterNetworkAddressUpdated(event: ConverterNetworkAddressUpdated): void { + const tokenConverter = getOrCreateTokenConvertor(event.address); + tokenConverter.converterNetwork = getConverterNetworkId(event.params.converterNetwork); + tokenConverter.save(); +} + +export function handleDestinationAddressUpdated(event: DestinationAddressUpdated): void { + const tokenConverter = getOrCreateTokenConvertor(event.address); + tokenConverter.destinationAddress = event.params.destinationAddress; + tokenConverter.save(); +} + +export function handleBaseAssetUpdated(event: BaseAssetUpdated): void { + const tokenConverter = getOrCreateTokenConvertor(event.address); + tokenConverter.baseAsset = event.params.newBaseAsset; + tokenConverter.save(); +} diff --git a/subgraphs/protocol-reserve/src/operations/create.ts b/subgraphs/protocol-reserve/src/operations/create.ts new file mode 100644 index 00000000..2d342734 --- /dev/null +++ b/subgraphs/protocol-reserve/src/operations/create.ts @@ -0,0 +1,37 @@ +import { Address } from '@graphprotocol/graph-ts'; + +import { TokenConverter as TokenConverterContract } from '../../generated/BTCBPrimeConverter/TokenConverter'; +import { RiskFund } from '../../generated/ConverterNetwork/RiskFund'; +import { TokenConverter, TokenConverterConfig } from '../../generated/schema'; +import { riskFundAddress, riskFundConverterAddress } from '../constants/addresses'; +import { getTokenConverterConfigId, getTokenConverterId } from '../utilities/ids'; + +export function createTokenConverter(tokenConverterAddress: Address): TokenConverter { + const tokenConverterContract = TokenConverterContract.bind(tokenConverterAddress); + const tokenConverter = new TokenConverter(getTokenConverterId(tokenConverterAddress)); + tokenConverter.destinationAddress = tokenConverterContract.destinationAddress(); + + if (tokenConverterAddress.equals(riskFundConverterAddress)) { + const riskFund = RiskFund.bind(riskFundAddress); + tokenConverter.baseAsset = riskFund.convertibleBaseAsset(); + } else { + tokenConverter.baseAsset = tokenConverterContract.baseAsset(); + } + tokenConverter.paused = false; + tokenConverter.save(); + return tokenConverter; +} + +export function createTokenConverterConfig( + tokenConverterAddress: Address, + tokenAddressIn: Address, + tokenAddressOut: Address, +): TokenConverterConfig { + const tokenConverterConfig = new TokenConverterConfig( + getTokenConverterConfigId(tokenConverterAddress, tokenAddressIn, tokenAddressOut), + ); + tokenConverterConfig.tokenConverter = getTokenConverterId(tokenConverterAddress); + tokenConverterConfig.tokenAddressIn = tokenAddressIn; + tokenConverterConfig.tokenAddressOut = tokenAddressOut; + return tokenConverterConfig; +} diff --git a/subgraphs/protocol-reserve/src/operations/delete.ts b/subgraphs/protocol-reserve/src/operations/delete.ts new file mode 100644 index 00000000..4c0d8b13 --- /dev/null +++ b/subgraphs/protocol-reserve/src/operations/delete.ts @@ -0,0 +1,6 @@ +import { Address } from '@graphprotocol/graph-ts'; +import { store } from '@graphprotocol/graph-ts'; + +export function deleteTokenConvertor(tokenConverterAddress: Address): void { + store.remove('TokenConverter', tokenConverterAddress.toHex()); +} diff --git a/subgraphs/protocol-reserve/src/operations/get.ts b/subgraphs/protocol-reserve/src/operations/get.ts new file mode 100644 index 00000000..d8eb2dea --- /dev/null +++ b/subgraphs/protocol-reserve/src/operations/get.ts @@ -0,0 +1,20 @@ +import { Address } from '@graphprotocol/graph-ts'; + +import { TokenConverter, TokenConverterConfig } from '../../generated/schema'; +import { getTokenConverterConfigId, getTokenConverterId } from '../utilities/ids'; + +export function getTokenConverter(tokenConverterAddress: Address): TokenConverter | null { + const id = getTokenConverterId(tokenConverterAddress); + const tokenConverter = TokenConverter.load(id); + return tokenConverter; +} + +export function getTokenConverterConfig( + tokenConverterAddress: Address, + tokenAddressIn: Address, + tokenAddressOut: Address, +): TokenConverterConfig | null { + const id = getTokenConverterConfigId(tokenConverterAddress, tokenAddressIn, tokenAddressOut); + const tokenConverterConfig = TokenConverterConfig.load(id); + return tokenConverterConfig; +} diff --git a/subgraphs/protocol-reserve/src/operations/getOrCreate.ts b/subgraphs/protocol-reserve/src/operations/getOrCreate.ts new file mode 100644 index 00000000..f53a1432 --- /dev/null +++ b/subgraphs/protocol-reserve/src/operations/getOrCreate.ts @@ -0,0 +1,59 @@ +import { Address } from '@graphprotocol/graph-ts'; + +import { ConverterNetwork, TokenConverter, TokenConverterConfig } from '../../generated/schema'; +import { getConverterNetworkId } from '../utilities/ids'; +import { createTokenConverter, createTokenConverterConfig } from './create'; +import { getTokenConverter, getTokenConverterConfig } from './get'; + +/** + * TokenConverters are hardcoded in the subgraph definition + * + * @param tokenConverterAddress + * @returns TokenConverter Entity + */ +export function getOrCreateTokenConvertor(tokenConverterAddress: Address): TokenConverter { + let tokenConverter = getTokenConverter(tokenConverterAddress); + + if (!tokenConverter) { + tokenConverter = createTokenConverter(tokenConverterAddress); + } + + return tokenConverter; +} + +/** + * ConverterNetwork is hardcoded in the subgraph definition + * + * @param converterNetworkAddress + * @returns + */ +export function getOrCreateConverterNetwork(converterNetworkAddress: Address): ConverterNetwork { + let converterNetwork = ConverterNetwork.load(getConverterNetworkId(converterNetworkAddress)); + + if (!converterNetwork) { + converterNetwork = new ConverterNetwork(getConverterNetworkId(converterNetworkAddress)); + } + + return converterNetwork; +} + +export function getOrCreateTokenConverterConfig( + tokenConverterAddress: Address, + tokenAddressIn: Address, + tokenAddressOut: Address, +): TokenConverterConfig { + let tokenConverterConfig = getTokenConverterConfig( + tokenConverterAddress, + tokenAddressIn, + tokenAddressOut, + ); + + if (!tokenConverterConfig) { + tokenConverterConfig = createTokenConverterConfig( + tokenConverterAddress, + tokenAddressIn, + tokenAddressOut, + ); + } + return tokenConverterConfig; +} diff --git a/subgraphs/protocol-reserve/src/operations/updateOrCreate.ts b/subgraphs/protocol-reserve/src/operations/updateOrCreate.ts new file mode 100644 index 00000000..5e572947 --- /dev/null +++ b/subgraphs/protocol-reserve/src/operations/updateOrCreate.ts @@ -0,0 +1,19 @@ +import { Address } from '@graphprotocol/graph-ts'; + +import { ConversionConfigUpdated__Params } from '../../generated/BTCBPrimeConverter/TokenConverter'; +import { ConversionAccessibility } from '../constants/index'; +import { getOrCreateTokenConverterConfig } from './getOrCreate'; + +export function updateOrCreateTokenConverterConfig( + tokenConverterAddress: Address, + params: ConversionConfigUpdated__Params, +): void { + const tokenConverterConfig = getOrCreateTokenConverterConfig( + tokenConverterAddress, + params.tokenAddressIn, + params.tokenAddressOut, + ); + tokenConverterConfig.incentive = params.newIncentive; + tokenConverterConfig.access = ConversionAccessibility[params.newAccess]; + tokenConverterConfig.save(); +} diff --git a/subgraphs/protocol-reserve/src/utilities/box.ts b/subgraphs/protocol-reserve/src/utilities/box.ts new file mode 100644 index 00000000..6d1a1d18 --- /dev/null +++ b/subgraphs/protocol-reserve/src/utilities/box.ts @@ -0,0 +1,9 @@ +class Box { + value: T; + + constructor(value: T) { + this.value = value; + } +} + +export default Box; diff --git a/subgraphs/protocol-reserve/src/utilities/exponentToBigDecimal.ts b/subgraphs/protocol-reserve/src/utilities/exponentToBigDecimal.ts new file mode 100644 index 00000000..d92aadca --- /dev/null +++ b/subgraphs/protocol-reserve/src/utilities/exponentToBigDecimal.ts @@ -0,0 +1,11 @@ +import { BigDecimal } from '@graphprotocol/graph-ts'; + +function exponentToBigDecimal(decimals: i32): BigDecimal { + let bd = BigDecimal.fromString('1'); + for (let i = 0; i < decimals; i++) { + bd = bd.times(BigDecimal.fromString('10')); + } + return bd; +} + +export default exponentToBigDecimal; diff --git a/subgraphs/protocol-reserve/src/utilities/exponentToBigInt.ts b/subgraphs/protocol-reserve/src/utilities/exponentToBigInt.ts new file mode 100644 index 00000000..dd63f053 --- /dev/null +++ b/subgraphs/protocol-reserve/src/utilities/exponentToBigInt.ts @@ -0,0 +1,11 @@ +import { BigInt } from '@graphprotocol/graph-ts'; + +function exponentToBigInt(decimals: i32): BigInt { + let bd = BigInt.fromString('1'); + for (let i = 0; i < decimals; i++) { + bd = bd.times(BigInt.fromString('10')); + } + return bd; +} + +export default exponentToBigInt; diff --git a/subgraphs/protocol-reserve/src/utilities/ids.ts b/subgraphs/protocol-reserve/src/utilities/ids.ts new file mode 100644 index 00000000..93ea0eea --- /dev/null +++ b/subgraphs/protocol-reserve/src/utilities/ids.ts @@ -0,0 +1,22 @@ +import { Address } from '@graphprotocol/graph-ts'; + +const SEPERATOR = '-'; + +const joinIds = (idArray: Array): string => idArray.join(SEPERATOR); + +export const getTokenConverterId = (address: Address): string => joinIds([address.toHexString()]); + +export const getConverterNetworkId = (address: Address): string => joinIds([address.toHexString()]); + +type TOKEN_CONVERTER_CONFIG_ID = string; + +export const getTokenConverterConfigId = ( + tokenConverterAddress: Address, + tokenAddressIn: Address, + tokenAddressOut: Address, +): TOKEN_CONVERTER_CONFIG_ID => + joinIds([ + tokenConverterAddress.toHexString(), + tokenAddressIn.toHexString(), + tokenAddressOut.toHexString(), + ]); diff --git a/subgraphs/protocol-reserve/src/utilities/index.ts b/subgraphs/protocol-reserve/src/utilities/index.ts new file mode 100644 index 00000000..c454360c --- /dev/null +++ b/subgraphs/protocol-reserve/src/utilities/index.ts @@ -0,0 +1,5 @@ +export { default as getExchangeRateBigDecimal } from './getExchangeRateBigDecimal'; +export { default as getTokenPriceInCents } from './getTokenPriceInCents'; +export { default as exponentToBigDecimal } from './exponentToBigDecimal'; +export { default as exponentToBigInt } from './exponentToBigInt'; +export { default as valueOrNotAvailableIntIfReverted } from './valueOrNotAvailableIntIfReverted'; diff --git a/subgraphs/protocol-reserve/src/utilities/valueOrNotAvailableIntIfReverted.ts b/subgraphs/protocol-reserve/src/utilities/valueOrNotAvailableIntIfReverted.ts new file mode 100644 index 00000000..b51b0c2c --- /dev/null +++ b/subgraphs/protocol-reserve/src/utilities/valueOrNotAvailableIntIfReverted.ts @@ -0,0 +1,10 @@ +import { BigInt, ethereum } from '@graphprotocol/graph-ts'; + +import { NOT_AVAILABLE_BIG_INT } from '../constants'; + +// checks if a call reverted, in case it is we return -1 to indicate the wanted value is not available +function valueOrNotAvailableIntIfReverted(callResult: ethereum.CallResult): BigInt { + return callResult.reverted ? NOT_AVAILABLE_BIG_INT : callResult.value; +} + +export default valueOrNotAvailableIntIfReverted; diff --git a/subgraphs/protocol-reserve/template.yaml b/subgraphs/protocol-reserve/template.yaml new file mode 100644 index 00000000..f5f5c3a1 --- /dev/null +++ b/subgraphs/protocol-reserve/template.yaml @@ -0,0 +1,221 @@ +specVersion: 0.0.4 +description: Venus is an open-source protocol for algorithmic, efficient Money Markets on the BSC blockchain. +repository: https://github.com/VenusProtocol/subgraphs +schema: + file: ./schema.graphql +dataSources: + - name: ConverterNetwork + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ converterNetworkAddress }}" + abi: ConverterNetwork + startBlock: {{ startBlock }} + mapping: + kind: ethereum/events + apiVersion: 0.0.7 + language: wasm/assemblyscript + file: ./src/mappings/converterNetwork.ts + entities: + - ConverterNetwork + abis: + - name: ConverterNetwork + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/TokenConverter/ConverterNetwork.sol/ConverterNetwork.json + - name: RiskFund + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFundGetters.json + eventHandlers: + - event: ConverterAdded(indexed address) + handler: handleConverterAdded + - event: ConverterRemoved(indexed address) + handler: handleConverterRemoved + + - name: BTCBPrimeConverter + kind: ethereum/contract + network: {{ network }} + source: + abi: TokenConverter + address: "{{ btcbPrimeConverterAddress }}" + startBlock: {{ startBlock }} + mapping: + kind: ethereum/events + apiVersion: 0.0.7 + language: wasm/assemblyscript + file: ./src/mappings/tokenConverter.ts + entities: + - TokenConverter + abis: + - name: TokenConverter + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/TokenConverter/SingleTokenConverter.sol/SingleTokenConverter.json + - name: RiskFund + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFundGetters.json + eventHandlers: + - event: ConversionConfigUpdated(indexed address,indexed address,uint256,uint256,uint8,uint8) + handler: handleConversionConfigUpdated + - event: ConversionPaused(indexed address) + handler: handleConversionPaused + - event: ConversionResumed(indexed address) + handler: handleConversionResumed + - event: ConverterNetworkAddressUpdated(indexed address,indexed address) + handler: handleConverterNetworkAddressUpdated + - event: DestinationAddressUpdated(indexed address,indexed address) + handler: handleDestinationAddressUpdated + - event: BaseAssetUpdated(indexed address,indexed address) + handler: handleDestinationAddressUpdated + - name: ETHPrimeConverter + kind: ethereum/contract + network: {{ network }} + source: + abi: TokenConverter + address: "{{ ethPrimeConverterAddress }}" + startBlock: {{ startBlock }} + mapping: + kind: ethereum/events + apiVersion: 0.0.7 + language: wasm/assemblyscript + file: ./src/mappings/tokenConverter.ts + entities: + - TokenConverter + abis: + - name: TokenConverter + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/TokenConverter/SingleTokenConverter.sol/SingleTokenConverter.json + - name: RiskFund + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFundGetters.json + eventHandlers: + - event: ConversionConfigUpdated(indexed address,indexed address,uint256,uint256,uint8,uint8) + handler: handleConversionConfigUpdated + - event: ConversionPaused(indexed address) + handler: handleConversionPaused + - event: ConversionResumed(indexed address) + handler: handleConversionResumed + - event: ConverterNetworkAddressUpdated(indexed address,indexed address) + handler: handleConverterNetworkAddressUpdated + - event: DestinationAddressUpdated(indexed address,indexed address) + handler: handleDestinationAddressUpdated + - event: BaseAssetUpdated(indexed address,indexed address) + handler: handleDestinationAddressUpdated + - name: RiskFundConverter + kind: ethereum/contract + network: {{ network }} + source: + abi: TokenConverter + address: "{{ riskFundConverterAddress }}" + startBlock: {{ startBlock }} + mapping: + kind: ethereum/events + apiVersion: 0.0.7 + language: wasm/assemblyscript + file: ./src/mappings/tokenConverter.ts + entities: + - TokenConverter + abis: + - name: TokenConverter + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/TokenConverter/RiskFundConverter.sol/RiskFundConverter.json + - name: RiskFund + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFundGetters.json + eventHandlers: + - event: ConversionConfigUpdated(indexed address,indexed address,uint256,uint256,uint8,uint8) + handler: handleConversionConfigUpdated + - event: ConversionPaused(indexed address) + handler: handleConversionPaused + - event: ConversionResumed(indexed address) + handler: handleConversionResumed + - event: ConverterNetworkAddressUpdated(indexed address,indexed address) + handler: handleConverterNetworkAddressUpdated + - event: DestinationAddressUpdated(indexed address,indexed address) + handler: handleDestinationAddressUpdated + - name: USDCPrimeConverter + kind: ethereum/contract + network: {{ network }} + source: + abi: TokenConverter + address: "{{ usdcPrimeConverterAddress }}" + startBlock: {{ startBlock }} + mapping: + kind: ethereum/events + apiVersion: 0.0.7 + language: wasm/assemblyscript + file: ./src/mappings/tokenConverter.ts + entities: + - TokenConverter + abis: + - name: TokenConverter + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/TokenConverter/SingleTokenConverter.sol/SingleTokenConverter.json + - name: RiskFund + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFundGetters.json + eventHandlers: + - event: ConversionConfigUpdated(indexed address,indexed address,uint256,uint256,uint8,uint8) + handler: handleConversionConfigUpdated + - event: ConversionPaused(indexed address) + handler: handleConversionPaused + - event: ConversionResumed(indexed address) + handler: handleConversionResumed + - event: ConverterNetworkAddressUpdated(indexed address,indexed address) + handler: handleConverterNetworkAddressUpdated + - event: DestinationAddressUpdated(indexed address,indexed address) + handler: handleDestinationAddressUpdated + - event: BaseAssetUpdated(indexed address,indexed address) + handler: handleDestinationAddressUpdated + - name: USDTPrimeConverter + kind: ethereum/contract + network: {{ network }} + source: + abi: TokenConverter + address: "{{ usdtPrimeConverterAddress }}" + startBlock: {{ startBlock }} + mapping: + kind: ethereum/events + apiVersion: 0.0.7 + language: wasm/assemblyscript + file: ./src/mappings/tokenConverter.ts + entities: + - TokenConverter + abis: + - name: TokenConverter + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/TokenConverter/SingleTokenConverter.sol/SingleTokenConverter.json + - name: RiskFund + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFundGetters.json + eventHandlers: + - event: ConversionConfigUpdated(indexed address,indexed address,uint256,uint256,uint8,uint8) + handler: handleConversionConfigUpdated + - event: ConversionPaused(indexed address) + handler: handleConversionPaused + - event: ConversionResumed(indexed address) + handler: handleConversionResumed + - event: ConverterNetworkAddressUpdated(indexed address,indexed address) + handler: handleConverterNetworkAddressUpdated + - event: DestinationAddressUpdated(indexed address,indexed address) + handler: handleDestinationAddressUpdated + - event: BaseAssetUpdated(indexed address,indexed address) + handler: handleDestinationAddressUpdated + - name: XVSVaultConverter + kind: ethereum/contract + network: {{ network }} + source: + abi: TokenConverter + address: "{{ xvsVaultConverterAddress }}" + startBlock: {{ startBlock }} + mapping: + kind: ethereum/events + apiVersion: 0.0.7 + language: wasm/assemblyscript + file: ./src/mappings/tokenConverter.ts + entities: + - TokenConverter + abis: + - name: TokenConverter + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/TokenConverter/SingleTokenConverter.sol/SingleTokenConverter.json + - name: RiskFund + file: ../../node_modules/@venusprotocol/protocol-reserve/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFundGetters.json + eventHandlers: + - event: ConversionConfigUpdated(indexed address,indexed address,uint256,uint256,uint8,uint8) + handler: handleConversionConfigUpdated + - event: ConversionPaused(indexed address) + handler: handleConversionPaused + - event: ConversionResumed(indexed address) + handler: handleConversionResumed + - event: ConverterNetworkAddressUpdated(indexed address,indexed address) + handler: handleConverterNetworkAddressUpdated + - event: DestinationAddressUpdated(indexed address,indexed address) + handler: handleDestinationAddressUpdated + - event: BaseAssetUpdated(indexed address,indexed address) + handler: handleBaseAssetUpdated diff --git a/subgraphs/protocol-reserve/tests/ConverterNetwork/events.ts b/subgraphs/protocol-reserve/tests/ConverterNetwork/events.ts new file mode 100644 index 00000000..33388823 --- /dev/null +++ b/subgraphs/protocol-reserve/tests/ConverterNetwork/events.ts @@ -0,0 +1,38 @@ +import { Address, ethereum } from '@graphprotocol/graph-ts'; +import { newMockEvent } from 'matchstick-as'; + +import { + ConverterAdded, + ConverterRemoved, +} from '../../generated/ConverterNetwork/ConverterNetwork'; + +export const createConverterAddedEvent = ( + converterNetworkAddress: Address, + tokenConverterAddress: Address, +): ConverterAdded => { + const event = changetype(newMockEvent()); + event.address = converterNetworkAddress; + event.parameters = []; + const converterParam = new ethereum.EventParam( + 'converter', + ethereum.Value.fromAddress(tokenConverterAddress), + ); + event.parameters.push(converterParam); + + return event; +}; + +export const createConverterRemovedEvent = ( + converterNetworkAddress: Address, + tokenConverterAddress: Address, +): ConverterRemoved => { + const event = changetype(newMockEvent()); + event.address = converterNetworkAddress; + event.parameters = []; + const converterParam = new ethereum.EventParam( + 'converter', + ethereum.Value.fromAddress(tokenConverterAddress), + ); + event.parameters.push(converterParam); + return event; +}; diff --git a/subgraphs/protocol-reserve/tests/ConverterNetwork/index.test.ts b/subgraphs/protocol-reserve/tests/ConverterNetwork/index.test.ts new file mode 100644 index 00000000..d9293863 --- /dev/null +++ b/subgraphs/protocol-reserve/tests/ConverterNetwork/index.test.ts @@ -0,0 +1,59 @@ +import { Address } from '@graphprotocol/graph-ts'; +import { assert, beforeAll, describe, test } from 'matchstick-as/assembly/index'; + +import { handleConverterAdded, handleConverterRemoved } from '../../src/mappings/converterNetwork'; +import { getConverterNetworkId, getTokenConverterId } from '../../src/utilities/ids'; +import { createTokenConverterMock } from '../TokenConverter/mocks'; +import { createConverterAddedEvent, createConverterRemovedEvent } from './events'; + +const converterNetworkAddress = Address.fromString('0x0000000000000000000000000000000000000ccc'); +const tokenConverter1Address = Address.fromString('0x0000000000000000000000000000000000000111'); +const tokenConverter2Address = Address.fromString('0x0000000000000000000000000000000000000222'); + +const token1Address = Address.fromString('0x000000000000000000000000000000000000c111'); +const destination1Address = Address.fromString('0x000000000000000000000000000000000000d111'); + +beforeAll(() => { + createTokenConverterMock(tokenConverter1Address, destination1Address, token1Address); + createTokenConverterMock(tokenConverter2Address, destination1Address, token1Address); +}); + +describe('Converter Network', () => { + test('should index adding token converter', () => { + const converterAddedEvent = createConverterAddedEvent( + converterNetworkAddress, + tokenConverter1Address, + ); + + handleConverterAdded(converterAddedEvent); + + const converterNetworkId = getConverterNetworkId(converterNetworkAddress); + const tokenConverterId = getTokenConverterId(tokenConverter1Address); + assert.fieldEquals('TokenConverter', tokenConverterId, 'id', tokenConverterId); + assert.fieldEquals('TokenConverter', tokenConverterId, 'converterNetwork', converterNetworkId); + }); + + test('should index removing token converter', () => { + const tokenConverterId = getTokenConverterId(tokenConverter2Address); + const converterNetworkId = getConverterNetworkId(converterNetworkAddress); + const converterAddedEvent = createConverterAddedEvent( + converterNetworkAddress, + tokenConverter2Address, + ); + + handleConverterAdded(converterAddedEvent); + + assert.fieldEquals('TokenConverter', tokenConverterId, 'id', tokenConverterId); + assert.fieldEquals('TokenConverter', tokenConverterId, 'converterNetwork', converterNetworkId); + + const converterRemovedEvent = createConverterRemovedEvent( + converterNetworkAddress, + tokenConverter2Address, + ); + + handleConverterRemoved(converterRemovedEvent); + + assert.fieldEquals('TokenConverter', tokenConverterId, 'id', tokenConverterId); + assert.fieldEquals('TokenConverter', tokenConverterId, 'converterNetwork', 'null'); + }); +}); diff --git a/subgraphs/protocol-reserve/tests/TokenConverter/events.ts b/subgraphs/protocol-reserve/tests/TokenConverter/events.ts new file mode 100644 index 00000000..d2e2a1ce --- /dev/null +++ b/subgraphs/protocol-reserve/tests/TokenConverter/events.ts @@ -0,0 +1,150 @@ +import { Address, BigInt, ethereum } from '@graphprotocol/graph-ts'; +import { newMockEvent } from 'matchstick-as'; + +import { + BaseAssetUpdated, + ConversionConfigUpdated, + ConversionPaused, + ConversionResumed, + ConverterNetworkAddressUpdated, + DestinationAddressUpdated, +} from '../../generated/BTCBPrimeConverter/TokenConverter'; + +export const createConversionConfigUpdatedEvent = ( + tokenConverterAddress: Address, + tokenInAddress: Address, + tokenOutAddress: Address, + oldIncentive: string, + newIncentive: string, + oldAccess: string, + newAccess: string, +): ConversionConfigUpdated => { + const event = changetype(newMockEvent()); + event.address = tokenConverterAddress; + event.parameters = []; + + const tokenAddressInParam = new ethereum.EventParam( + 'tokenAddressIn', + ethereum.Value.fromAddress(tokenInAddress), + ); + event.parameters.push(tokenAddressInParam); + + const tokenAddressOutParam = new ethereum.EventParam( + 'tokenAddressOut', + ethereum.Value.fromAddress(tokenOutAddress), + ); + event.parameters.push(tokenAddressOutParam); + + const oldIncentiveValue = ethereum.Value.fromUnsignedBigInt(BigInt.fromString(oldIncentive)); + const oldIncentiveParam = new ethereum.EventParam('oldIncentive', oldIncentiveValue); + event.parameters.push(oldIncentiveParam); + + const newIncentiveValue = ethereum.Value.fromUnsignedBigInt(BigInt.fromString(newIncentive)); + const newIncentiveParam = new ethereum.EventParam('newIncentive', newIncentiveValue); + event.parameters.push(newIncentiveParam); + + const oldAccessValue = ethereum.Value.fromUnsignedBigInt(BigInt.fromString(oldAccess)); + const oldAccessParam = new ethereum.EventParam('oldAccess', oldAccessValue); + event.parameters.push(oldAccessParam); + + const newAccessValue = ethereum.Value.fromUnsignedBigInt(BigInt.fromString(newAccess)); + const newAccessParam = new ethereum.EventParam('newAccess', newAccessValue); + event.parameters.push(newAccessParam); + + return event; +}; + +export const createConversionPausedEvent = ( + tokenConverterAddress: Address, + sender: Address, +): ConversionPaused => { + const event = changetype(newMockEvent()); + event.address = tokenConverterAddress; + event.parameters = []; + const senderParam = new ethereum.EventParam('sender', ethereum.Value.fromAddress(sender)); + event.parameters.push(senderParam); + + return event; +}; + +export const createConversionResumedEvent = ( + tokenConverterAddress: Address, + sender: Address, +): ConversionResumed => { + const event = changetype(newMockEvent()); + event.address = tokenConverterAddress; + event.parameters = []; + const senderParam = new ethereum.EventParam('sender', ethereum.Value.fromAddress(sender)); + event.parameters.push(senderParam); + + return event; +}; + +export const createConverterNetworkAddressUpdatedEvent = ( + tokenConverterAddress: Address, + oldConverterNetwork: Address, + converterNetwork: Address, +): ConverterNetworkAddressUpdated => { + const event = changetype(newMockEvent()); + event.address = tokenConverterAddress; + event.parameters = []; + const oldConverterNetworkParam = new ethereum.EventParam( + 'oldConverterNetwork', + ethereum.Value.fromAddress(oldConverterNetwork), + ); + event.parameters.push(oldConverterNetworkParam); + + const converterNetworkParam = new ethereum.EventParam( + 'converterNetwork', + ethereum.Value.fromAddress(converterNetwork), + ); + event.parameters.push(converterNetworkParam); + + return event; +}; + +export const createDestinationAddressUpdatedEvent = ( + tokenConverterAddress: Address, + oldDestinationAddress: Address, + destinationAddress: Address, +): DestinationAddressUpdated => { + const event = changetype(newMockEvent()); + event.address = tokenConverterAddress; + event.parameters = []; + const oldDestinationAddressParam = new ethereum.EventParam( + 'oldDestinationAddress', + ethereum.Value.fromAddress(oldDestinationAddress), + ); + event.parameters.push(oldDestinationAddressParam); + + const destinationAddressParam = new ethereum.EventParam( + 'destinationAddress', + ethereum.Value.fromAddress(destinationAddress), + ); + event.parameters.push(destinationAddressParam); + + return event; +}; + +export const createBaseAssetUpdatedEvent = ( + tokenConverterAddress: Address, + oldBaseAsset: Address, + newBaseAsset: Address, +): BaseAssetUpdated => { + const event = changetype(newMockEvent()); + event.address = tokenConverterAddress; + event.parameters = []; + const oldBaseAssetParam = new ethereum.EventParam( + 'oldBaseAsset', + ethereum.Value.fromAddress(oldBaseAsset), + ); + event.parameters.push(oldBaseAssetParam); + + const newBaseAssetParam = new ethereum.EventParam( + 'newBaseAsset', + ethereum.Value.fromAddress(newBaseAsset), + ); + event.parameters.push(newBaseAssetParam); + + return event; +}; diff --git a/subgraphs/protocol-reserve/tests/TokenConverter/index.test.ts b/subgraphs/protocol-reserve/tests/TokenConverter/index.test.ts new file mode 100644 index 00000000..5ded5732 --- /dev/null +++ b/subgraphs/protocol-reserve/tests/TokenConverter/index.test.ts @@ -0,0 +1,158 @@ +import { Address } from '@graphprotocol/graph-ts'; +import { assert, beforeAll, describe, test } from 'matchstick-as/assembly/index'; + +import { TokenConverter } from '../../generated/schema'; +import { + handleBaseAssetUpdated, + handleConversionConfigUpdated, + handleConversionPaused, + handleConversionResumed, + handleConverterNetworkAddressUpdated, + handleDestinationAddressUpdated, +} from '../../src/mappings/tokenConverter'; +import { getTokenConverterId } from '../../src/utilities/ids'; +import { + createBaseAssetUpdatedEvent, + createConversionConfigUpdatedEvent, + createConversionPausedEvent, + createConversionResumedEvent, + createConverterNetworkAddressUpdatedEvent, + createDestinationAddressUpdatedEvent, +} from './events'; +import { createTokenConverterMock } from './mocks'; + +const user = Address.fromString('0x0000000000000000000000000000000000000aaa'); +const converterNetworkAddress = Address.fromString('0x0000000000000000000000000000000000000ccc'); +const tokenConverter1Address = Address.fromString('0x0000000000000000000000000000000000000111'); +const tokenConverter2Address = Address.fromString('0x0000000000000000000000000000000000000222'); + +const token1Address = Address.fromString('0x000000000000000000000000000000000000c111'); +const token2Address = Address.fromString('0x000000000000000000000000000000000000c222'); +const token3Address = Address.fromString('0x000000000000000000000000000000000000c333'); +const token4Address = Address.fromString('0x000000000000000000000000000000000000c444'); + +const destination1Address = Address.fromString('0x000000000000000000000000000000000000d111'); +const destination2Address = Address.fromString('0x000000000000000000000000000000000000d222'); + +beforeAll(() => { + createTokenConverterMock(tokenConverter1Address, destination1Address, token3Address); + createTokenConverterMock(tokenConverter2Address, destination1Address, token3Address); +}); + +describe('Token Converter', () => { + test('should index new token converter config', () => { + handleConversionConfigUpdated( + createConversionConfigUpdatedEvent( + tokenConverter1Address, + token1Address, + token2Address, + '200000000000000000', + '300000000000000000', + '0', + '1', + ), + ); + const tokenConverterId = getTokenConverterId(tokenConverter1Address); + + assert.fieldEquals('TokenConverter', tokenConverterId, 'id', tokenConverterId); + const tokenConverter = TokenConverter.load(tokenConverterId)!; + + const tokenConfigs = tokenConverter.configs.load(); + assert.i32Equals(tokenConfigs.length, 1); + assert.addressEquals(Address.fromBytes(tokenConfigs[0].tokenAddressIn), token1Address); + assert.addressEquals(Address.fromBytes(tokenConfigs[0].tokenAddressOut), token2Address); + assert.stringEquals(tokenConfigs[0].incentive.toString(), '300000000000000000'); + assert.stringEquals(tokenConfigs[0].access, 'ALL'); + }); + + test('should index updating existing token converter config', () => { + handleConversionConfigUpdated( + createConversionConfigUpdatedEvent( + tokenConverter1Address, + token1Address, + token2Address, + '300000000000000000', + '400000000000000000', + '1', + '3', + ), + ); + const tokenConverterId = getTokenConverterId(tokenConverter1Address); + assert.fieldEquals('TokenConverter', tokenConverterId, 'id', tokenConverterId); + + const tokenConverter = TokenConverter.load(tokenConverterId)!; + const tokenConfigs = tokenConverter.configs.load(); + assert.i32Equals(tokenConfigs.length, 1); + assert.addressEquals(Address.fromBytes(tokenConfigs[0].tokenAddressIn), token1Address); + assert.addressEquals(Address.fromBytes(tokenConfigs[0].tokenAddressOut), token2Address); + assert.stringEquals(tokenConfigs[0].incentive.toString(), '400000000000000000'); + assert.stringEquals(tokenConfigs[0].access, 'ONLY_FOR_USERS'); + }); + + test('should index pausing conversions', () => { + handleConversionPaused(createConversionPausedEvent(tokenConverter1Address, user)); + const tokenConverterId = getTokenConverterId(tokenConverter1Address); + assert.fieldEquals('TokenConverter', tokenConverterId, 'id', tokenConverterId); + assert.fieldEquals('TokenConverter', tokenConverterId, 'paused', 'true'); + }); + + test('should index resuming conversions', () => { + handleConversionResumed(createConversionResumedEvent(tokenConverter1Address, user)); + const tokenConverterId = getTokenConverterId(tokenConverter1Address); + assert.fieldEquals('TokenConverter', tokenConverterId, 'id', tokenConverterId); + assert.fieldEquals('TokenConverter', tokenConverterId, 'paused', 'false'); + }); + + test('should index updating converter network address', () => { + const newConverterNetworkAddress = Address.fromString( + '0x0000000000000000000000000000000000000ddd', + ); + handleConverterNetworkAddressUpdated( + createConverterNetworkAddressUpdatedEvent( + tokenConverter1Address, + converterNetworkAddress, + newConverterNetworkAddress, + ), + ); + const tokenConverterId = getTokenConverterId(tokenConverter1Address); + assert.fieldEquals('TokenConverter', tokenConverterId, 'id', tokenConverterId); + assert.fieldEquals( + 'TokenConverter', + tokenConverterId, + 'converterNetwork', + newConverterNetworkAddress.toHexString(), + ); + }); + + test('should index updating destination address', () => { + handleDestinationAddressUpdated( + createDestinationAddressUpdatedEvent( + tokenConverter2Address, + destination1Address, + destination2Address, + ), + ); + const tokenConverterId = getTokenConverterId(tokenConverter2Address); + assert.fieldEquals('TokenConverter', tokenConverterId, 'id', tokenConverterId); + assert.fieldEquals( + 'TokenConverter', + tokenConverterId, + 'destinationAddress', + destination2Address.toHexString(), + ); + }); + + test('should update indexing base asset', () => { + handleBaseAssetUpdated( + createBaseAssetUpdatedEvent(tokenConverter2Address, token3Address, token4Address), + ); + const tokenConverterId = getTokenConverterId(tokenConverter2Address); + assert.fieldEquals('TokenConverter', tokenConverterId, 'id', tokenConverterId); + assert.fieldEquals( + 'TokenConverter', + tokenConverterId, + 'baseAsset', + token4Address.toHexString(), + ); + }); +}); diff --git a/subgraphs/protocol-reserve/tests/TokenConverter/mocks.ts b/subgraphs/protocol-reserve/tests/TokenConverter/mocks.ts new file mode 100644 index 00000000..a1256005 --- /dev/null +++ b/subgraphs/protocol-reserve/tests/TokenConverter/mocks.ts @@ -0,0 +1,18 @@ +import { Address, ethereum } from '@graphprotocol/graph-ts'; +import { createMockedFunction } from 'matchstick-as'; + +export const createTokenConverterMock = ( + tokenConverterAddress: Address, + destinationAddress: Address, + baseAssetAddress: Address, +): void => { + createMockedFunction( + tokenConverterAddress, + 'destinationAddress', + 'destinationAddress():(address)', + ).returns([ethereum.Value.fromAddress(destinationAddress)]); + + createMockedFunction(tokenConverterAddress, 'baseAsset', 'baseAsset():(address)').returns([ + ethereum.Value.fromAddress(baseAssetAddress), + ]); +}; diff --git a/yarn.lock b/yarn.lock index 3171c825..2a65d6ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4402,7 +4402,7 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/governance-contracts@npm:1.4.0, @venusprotocol/governance-contracts@npm:^1.4.0, @venusprotocol/governance-contracts@npm:^1.4.0-dev.1": +"@venusprotocol/governance-contracts@npm:1.4.0, @venusprotocol/governance-contracts@npm:^1.4.0": version: 1.4.0 resolution: "@venusprotocol/governance-contracts@npm:1.4.0" dependencies: @@ -4420,7 +4420,18 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/isolated-pools@npm:2.5.0, @venusprotocol/isolated-pools@npm:^2.3.0, @venusprotocol/isolated-pools@npm:^2.5.0": +"@venusprotocol/governance-contracts@npm:^1.4.0-dev.1": + version: 1.4.0-dev.9 + resolution: "@venusprotocol/governance-contracts@npm:1.4.0-dev.9" + dependencies: + "@venusprotocol/solidity-utilities": ^1.1.0 + hardhat-deploy-ethers: ^0.3.0-beta.13 + module-alias: ^2.2.2 + checksum: 25583a20738973d2ade4a1fdf84dcacf0caec42004f5bf755fdfa29b3602f2b9184638f2d828359195bf8baa3b082797cad941874be1a91a61900b343420cead + languageName: node + linkType: hard + +"@venusprotocol/isolated-pools@npm:2.5.0, @venusprotocol/isolated-pools@npm:^2.5.0": version: 2.5.0 resolution: "@venusprotocol/isolated-pools@npm:2.5.0" dependencies: @@ -4436,6 +4447,22 @@ __metadata: languageName: node linkType: hard +"@venusprotocol/isolated-pools@npm:^2.3.0": + version: 2.4.0 + resolution: "@venusprotocol/isolated-pools@npm:2.4.0" + dependencies: + "@nomiclabs/hardhat-ethers": ^2.2.3 + "@openzeppelin/contracts": ^4.8.3 + "@openzeppelin/contracts-upgradeable": ^4.8.3 + "@openzeppelin/hardhat-upgrades": ^1.21.0 + "@solidity-parser/parser": ^0.13.2 + ethers: ^5.7.0 + hardhat-deploy: ^0.11.14 + module-alias: ^2.2.2 + checksum: c67b2d1eaf2ae7cae1e7b73799ec1dd0ffd3bc996bea09fc6e6c909f416f65fa168bd0690034ce8882da0d0b9a8825032dde3dd15bad392a5a5cad32bf697a73 + languageName: node + linkType: hard + "@venusprotocol/oracle@npm:^1.9.0": version: 1.9.0 resolution: "@venusprotocol/oracle@npm:1.9.0" @@ -4475,13 +4502,20 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/solidity-utilities@npm:1.3.0, @venusprotocol/solidity-utilities@npm:^1.1.0, @venusprotocol/solidity-utilities@npm:^1.2.0, @venusprotocol/solidity-utilities@npm:^1.3.0": +"@venusprotocol/solidity-utilities@npm:1.3.0, @venusprotocol/solidity-utilities@npm:^1.2.0, @venusprotocol/solidity-utilities@npm:^1.3.0": version: 1.3.0 resolution: "@venusprotocol/solidity-utilities@npm:1.3.0" checksum: d1109365a5e01959c47b25fb129373db93792e60bf1bc0ed324b63c2a64f6e4a7878ebf016cfade94bc41a2c1245d3e861fdc6b8c5844ac210ed1d73e7307e72 languageName: node linkType: hard +"@venusprotocol/solidity-utilities@npm:^1.1.0": + version: 1.1.0 + resolution: "@venusprotocol/solidity-utilities@npm:1.1.0" + checksum: 3b17ec451cd0ba5aaea76686c7bef35757fb158709214be094f73ebd0d643c79817159f7aa162cc694e1a5ee1f02b20e26211a65929113b985827959aae99fa7 + languageName: node + linkType: hard + "@venusprotocol/token-bridge@npm:1.0.0": version: 1.0.0 resolution: "@venusprotocol/token-bridge@npm:1.0.0" @@ -13240,6 +13274,16 @@ __metadata: languageName: node linkType: hard +"protocol-reserve-subgraph@workspace:subgraphs/protocol-reserve": + version: 0.0.0-use.local + resolution: "protocol-reserve-subgraph@workspace:subgraphs/protocol-reserve" + dependencies: + apollo-fetch: ^0.7.0 + urql: ^3.0.3 + venus-subgraph-utils: 0.0.0 + languageName: unknown + linkType: soft + "proxy-addr@npm:~2.0.7": version: 2.0.7 resolution: "proxy-addr@npm:2.0.7"