diff --git a/.env.example b/.env.example index afc3336b..ececd09c 100644 --- a/.env.example +++ b/.env.example @@ -15,3 +15,4 @@ ETHERSCAN_API_KEY= ARBISCAN_API_KEY= BLOCKNATIVE_API_KEY= DISCORD_WEBHOOK_URL= +GRAPH_URL= diff --git a/package.json b/package.json index eea187d6..0e1169a5 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "dependencies": { "@aws/dynamodb-data-mapper": "^0.7.3", "@aws/dynamodb-data-mapper-annotations": "^0.7.3", - "@badger-dao/sdk": "^1.19.1", + "@badger-dao/sdk": "^1.23.0", "@tsed/common": "6.95.9", "@tsed/core": "6.95.9", "@tsed/di": "6.95.9", @@ -55,7 +55,7 @@ "tslib": "^2.2.0" }, "devDependencies": { - "@badger-dao/sdk-mocks": "^1.18.13", + "@badger-dao/sdk-mocks": "^1.23.0", "@graphql-codegen/cli": "^2.3.0", "@graphql-codegen/typescript": "^2.7.3", "@graphql-codegen/typescript-graphql-request": "^4.5.3", diff --git a/serverless.yml b/serverless.yml index 9734dea3..6e2c27b4 100644 --- a/serverless.yml +++ b/serverless.yml @@ -59,7 +59,7 @@ custom: CYCLE_ANALYTICS_DATA: rewards-${self:custom.stage} PROTOCOL_DATA: protocol-data-${self:custom.stage} CHART_DATA: chart-data-${self:custom.stage} - GOVERNANCE_PROPOSALS_DATA: governance-proposals-data-${self:custom.stage} + INDEXING_META_DATA: indexing-meta-data-${self:custom.stage} merkleProofs: staging: 'badger-staging-merkle-proofs-v2' @@ -71,7 +71,7 @@ package: provider: name: aws - runtime: nodejs14.x + runtime: nodejs16.x memorySize: 2048 stage: staging region: us-west-1 @@ -93,6 +93,7 @@ provider: MATIC_RPC: ${env:MATIC_RPC} ARBITRUM_RPC: ${env:ARBITRUM_RPC} # 3rd party API keys + GRAPH_URL: ${env:GRAPH_URL} DISCORD_WEBHOOK_URL: ${env:DISCORD_WEBHOOK_URL} UNISWAP: 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2' SUSHISWAP: 'https://api.thegraph.com/subgraphs/name/sushiswap/exchange' @@ -120,7 +121,7 @@ provider: UNCLAIMED_SNAPSHOTS_DATA: ${self:custom.table.UNCLAIMED_SNAPSHOTS_DATA} PROTOCOL_DATA: ${self:custom.table.PROTOCOL_DATA} CHART_DATA: ${self:custom.table.CHART_DATA} - GOVERNANCE_PROPOSALS_DATA: ${self:custom.table.GOVERNANCE_PROPOSALS_DATA} + INDEXING_META_DATA: ${self:custom.table.INDEXING_META_DATA} # General Defintions REWARD_DATA: ${self:custom.merkleProofs.${self:custom.stage}} STAGE: ${opt:stage, self:provider.stage} @@ -443,34 +444,17 @@ resources: - AttributeName: 'id' AttributeType: 'S' - governanceProposalsData: + indexingMetaData: Type: AWS::DynamoDB::Table Properties: - TableName: ${self:custom.table.GOVERNANCE_PROPOSALS_DATA} + TableName: ${self:custom.table.INDEXING_META_DATA} BillingMode: PAY_PER_REQUEST KeySchema: - - AttributeName: 'idx' + - AttributeName: 'task' KeyType: 'HASH' - - AttributeName: 'createdAt' - KeyType: 'RANGE' AttributeDefinitions: - - AttributeName: 'idx' + - AttributeName: 'task' AttributeType: 'S' - - AttributeName: 'createdAt' - AttributeType: 'N' - - AttributeName: 'network' - AttributeType: 'S' - - AttributeName: 'updateBlock' - AttributeType: 'N' - GlobalSecondaryIndexes: - - IndexName: IndexGovernanceProposalsUpdateBlock - KeySchema: - - AttributeName: 'network' - KeyType: 'HASH' - - AttributeName: 'updateBlock' - KeyType: 'RANGE' - Projection: - ProjectionType: ALL yieldProjectionsTable: Type: AWS::DynamoDB::Table @@ -590,12 +574,3 @@ functions: name: ${self:service}-${self:custom.stage}-index-protocol-metrics-snapshots description: 'index protocol metrics' rate: rate(1 day) - - index-governance-proposals-events: - handler: src/indexers/governance-proposals-indexer.updateGovernanceProposals - timeout: 900 - events: - - schedule: - name: ${self:service}-${self:custom.stage}-index-governance-proposals - description: 'index onchain governance proposals events' - rate: rate(20 minutes) diff --git a/src/aws/models/governance-proposals-child.interface.ts b/src/aws/models/governance-proposals-child.interface.ts deleted file mode 100644 index ab90fb2f..00000000 --- a/src/aws/models/governance-proposals-child.interface.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { embed } from '@aws/dynamodb-data-mapper'; -import { attribute } from '@aws/dynamodb-data-mapper-annotations'; - -import { GovernanceProposalsStatuses } from './governance-proposals-statuses.interface'; - -export class GovernanceProposalsChild { - @attribute() - index!: number; - - @attribute() - value!: number; - - @attribute() - callData!: string; - - @attribute() - targetAddr!: string; - - @attribute() - predecessor!: string; - - @attribute({ memberType: embed(GovernanceProposalsStatuses) }) - executed!: GovernanceProposalsStatuses; - - @attribute() - sender!: string; -} diff --git a/src/aws/models/governance-proposals-disputes.interface.ts b/src/aws/models/governance-proposals-disputes.interface.ts deleted file mode 100644 index 93359f13..00000000 --- a/src/aws/models/governance-proposals-disputes.interface.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { attribute } from '@aws/dynamodb-data-mapper-annotations'; - -export class GovernanceProposalsDisputes { - @attribute() - name!: string; - - @attribute() - ruling!: boolean; - - @attribute() - sender!: string; - - @attribute() - status!: string; - - @attribute() - transactionHash!: string; - - @attribute() - blockNumber!: number; - - @attribute() - updatedAt!: number; -} diff --git a/src/aws/models/governance-proposals-statuses.interface.ts b/src/aws/models/governance-proposals-statuses.interface.ts deleted file mode 100644 index 130a3562..00000000 --- a/src/aws/models/governance-proposals-statuses.interface.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { attribute } from '@aws/dynamodb-data-mapper-annotations'; - -export class GovernanceProposalsStatuses { - @attribute() - name!: string; - - @attribute() - sender!: string; - - @attribute() - status!: string; - - @attribute() - value!: number; - - @attribute() - transactionHash!: string; - - @attribute() - blockNumber!: number; - - @attribute() - updatedAt!: number; -} diff --git a/src/aws/models/governance-proposals.model.ts b/src/aws/models/governance-proposals.model.ts deleted file mode 100644 index c12fa2f6..00000000 --- a/src/aws/models/governance-proposals.model.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { embed } from '@aws/dynamodb-data-mapper'; -import { attribute, hashKey, rangeKey, table } from '@aws/dynamodb-data-mapper-annotations'; -import { Network } from '@badger-dao/sdk'; - -import { GOVERNANCE_PROPOSALS_DATA } from '../../config/constants'; -import { GovernanceProposalsChild } from './governance-proposals-child.interface'; -import { GovernanceProposalsDisputes } from './governance-proposals-disputes.interface'; -import { GovernanceProposalsStatuses } from './governance-proposals-statuses.interface'; - -@table(GOVERNANCE_PROPOSALS_DATA) -export class GovernanceProposals { - @hashKey() - idx!: string; - - @attribute() - proposalId!: string; - - @rangeKey() - createdAt!: number; - - @attribute({ - indexKeyConfigurations: { - IndexGovernanceProposalsUpdateBlock: 'HASH', - }, - }) - network!: string; - - @attribute() - contractAddr!: string; - - @attribute() - targetAddr!: string; - - @attribute() - value!: number; - - @attribute() - callData!: string; - - @attribute() - readyTime!: number; - - @attribute() - sender!: string; - - @attribute() - currentStatus!: string; - - @attribute() - creationBlock!: number; - - @attribute({ - indexKeyConfigurations: { - IndexGovernanceProposalsUpdateBlock: 'RANGE', - }, - }) - updateBlock!: number; - - @attribute({ memberType: embed(GovernanceProposalsStatuses) }) - statuses!: Array; - - @attribute({ memberType: embed(GovernanceProposalsDisputes) }) - disputes!: Array; - - @attribute({ memberType: embed(GovernanceProposalsChild) }) - children!: Array; - - static genIdx(network: Network, contractAddr: string, proposalId: string) { - return `${network}-${contractAddr}-${proposalId}`; - } -} diff --git a/src/aws/models/indexing-metadata.model.ts b/src/aws/models/indexing-metadata.model.ts new file mode 100644 index 00000000..0e11f9eb --- /dev/null +++ b/src/aws/models/indexing-metadata.model.ts @@ -0,0 +1,12 @@ +import { attribute, hashKey, table } from '@aws/dynamodb-data-mapper-annotations'; + +import { INDEXING_META_DATA } from '../../config/constants'; + +@table(INDEXING_META_DATA) +export class IndexingMetadata { + @hashKey() + task!: string; + + @attribute({ memberType: { type: 'Any' } }) + data!: T; +} diff --git a/src/chains/chains.utils.ts b/src/chains/chains.utils.ts index 3fe11699..07235709 100644 --- a/src/chains/chains.utils.ts +++ b/src/chains/chains.utils.ts @@ -18,8 +18,8 @@ export const SUPPORTED_NETWORKS = [ Network.Optimism, ]; -export function getSupportedChains(): Chain[] { - return SUPPORTED_NETWORKS.map((n) => getOrCreateChain(n)); +export function getSupportedChains(supportedNetworks = SUPPORTED_NETWORKS): Chain[] { + return supportedNetworks.map((n) => getOrCreateChain(n)); } export function getOrCreateChain(network?: Network): Chain { diff --git a/src/chains/config/chain.config.ts b/src/chains/config/chain.config.ts index 5b8ac217..f5c4b95d 100644 --- a/src/chains/config/chain.config.ts +++ b/src/chains/config/chain.config.ts @@ -3,6 +3,7 @@ import BadgerSDK, { GasPrices, getNetworkConfig, Network, SDKProvider } from '@b import { BadRequest, NotFound } from '@tsed/exceptions'; import { ethers } from 'ethers'; +import { GRAPH_URL } from '../../config/constants'; import { TOKENS } from '../../config/tokens.config'; import { TokenConfig } from '../../tokens/interfaces/token-config.interface'; import { ChainVaults } from '../vaults/chain.vaults'; @@ -22,7 +23,7 @@ export abstract class Chain { const { chainId } = config; this.chainId = chainId; this.vaults = new ChainVaults(network); - this.sdk = new BadgerSDK({ network, provider }); + this.sdk = new BadgerSDK({ network, provider, ...(GRAPH_URL ? { graphURL: GRAPH_URL } : {}) }); } get provider(): providers.MulticallProvider { diff --git a/src/config/constants.ts b/src/config/constants.ts index 0a99e89a..7f4894e4 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -21,7 +21,7 @@ export const YIELD_ESTIMATES_DATA = getEnvVar('YIELD_ESTIMATES_DATA'); export const VAULT_YIELD_DATA = getEnvVar('VAULT_YIELD_DATA'); export const PROTOCOL_DATA = getEnvVar('PROTOCOL_DATA'); export const CHART_DATA = getEnvVar('CHART_DATA'); -export const GOVERNANCE_PROPOSALS_DATA = getEnvVar('GOVERNANCE_PROPOSALS_DATA'); +export const INDEXING_META_DATA = getEnvVar('INDEXING_META_DATA'); export const YIELD_PROJECTIONS_DATA = getEnvVar('YIELD_PROJECTIONS_DATA'); // thegraph constants @@ -33,6 +33,7 @@ export const PANCAKESWAP_URL = getEnvVar('PANCAKESWAP'); export const QUICKSWAP_URL = getEnvVar('QUICKSWAP'); export const SWAPR_URL = getEnvVar('SWAPR'); export const BALANCER_URL = getEnvVar('BALANCER'); +export const GRAPH_URL = getEnvVar('GRAPH_URL'); // general constants export const STAGE = getEnvVar('STAGE'); diff --git a/src/controllers.ts b/src/controllers.ts index 831288cf..f9dd5782 100644 --- a/src/controllers.ts +++ b/src/controllers.ts @@ -3,7 +3,6 @@ import { AccountsV3Controller } from './accounts/accounts.v3.controller'; import { ChartsController } from './charts/charts.controller'; import { DevelopmentController } from './dev/dev.controller'; import { GasController } from './gas/gas.controller'; -import { GovernanceController } from './governance/governance.controller'; import { LeaderBoardsController } from './leaderboards/leaderboards.controller'; import { MetricsController } from './metrics/metrics.controller'; import { PricesController } from './prices/prices.controller'; @@ -45,7 +44,6 @@ export const V3_CONTROLLERS = [ MetricsController, PricesController, TokensController, - GovernanceController, DevelopmentController, diff --git a/src/governance/governance.constants.ts b/src/governance/governance.constants.ts deleted file mode 100644 index 89de53de..00000000 --- a/src/governance/governance.constants.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const DEFAULT_PAGE = 1; -export const DEFAULT_PAGE_SIZE = 10; - -export const MAX_PAGE_SIZE = 100; diff --git a/src/governance/governance.controller.ts b/src/governance/governance.controller.ts deleted file mode 100644 index 5714e168..00000000 --- a/src/governance/governance.controller.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Network } from '@badger-dao/sdk'; -import { Controller, Inject } from '@tsed/di'; -import { QueryParams } from '@tsed/platform-params'; -import { ContentType, Description, Get, Returns, Summary } from '@tsed/schema'; - -import { GovernanceProposals } from '../aws/models/governance-proposals.model'; -import { getOrCreateChain } from '../chains/chains.utils'; -import { PRODUCTION } from '../config/constants'; -import { NotFoundError } from '../errors/allocation/not.found.error'; -import { QueryParamError } from '../errors/validation/query.param.error'; -import { DEFAULT_PAGE, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from './governance.constants'; -import { GovernanceService } from './governance.service'; -import { GovernanceProposalsList } from './interfaces/governance.proposals.list'; -import { ProposalListResponse } from './responses/proposal.list.response'; -import { ProposalResponse } from './responses/proposal.response'; - -@Controller('/governance') -export class GovernanceController { - @Inject() - governanceService!: GovernanceService; - - @Get('/proposal') - @ContentType('json') - @Summary('Get a specific proposal') - @Description('Return a specific proposal for the requested chain') - @Returns(200, ProposalResponse) - @Returns(400).Description('Not a valid chain') - @Returns(404).Description('No data for id proposal') - @Returns(404).Description('Chain does not have requested data') - async getProposal( - @QueryParams('id') id: string, - @QueryParams('chain') chain?: Network, - ): Promise { - if (!id) { - throw new QueryParamError('id'); - } - - if (PRODUCTION) throw new NotFoundError(); - - return this.governanceService.getGovernanceProposal(getOrCreateChain(chain), id); - } - - @Get('/proposals/list') - @ContentType('json') - @Summary('Get a list of proposals') - @Description('Return a list of proposals for the requested chain') - @Returns(200, ProposalListResponse) - @Returns(400).Description('Not a valid chain') - async listProposals( - @QueryParams('chain') chain?: Network, - @QueryParams('page') page?: number, - @QueryParams('perPage') perPage?: number, - ): Promise { - if (PRODUCTION) throw new NotFoundError(); - - const pageInt = page ? Number(page) : DEFAULT_PAGE; - let perPageInt = perPage ? Number(perPage) : DEFAULT_PAGE_SIZE; - - if (perPageInt > MAX_PAGE_SIZE) perPageInt = MAX_PAGE_SIZE; - - return this.governanceService.listGovernanceProposals(getOrCreateChain(chain), pageInt, perPageInt); - } -} diff --git a/src/governance/governance.service.ts b/src/governance/governance.service.ts deleted file mode 100644 index df2e3816..00000000 --- a/src/governance/governance.service.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { GovernanceProposals } from '../aws/models/governance-proposals.model'; -import { Chain } from '../chains/config/chain.config'; -import { NodataForAddrError } from '../errors/allocation/nodata.for.addr.error'; -import { OutOfRangeError } from '../errors/validation/out.of.range.error'; -import { countProposalsByNetwork, getProposalByIdx, getProposalsList } from './governance.utils'; -import { GovernanceProposalsList } from './interfaces/governance.proposals.list'; - -export class GovernanceService { - async getGovernanceProposal(chain: Chain, id: string): Promise { - const proposal = await getProposalByIdx(chain, id); - - if (!proposal) { - throw new NodataForAddrError(id); - } - - return proposal; - } - - async listGovernanceProposals(chain: Chain, page: number, perPage: number): Promise { - const offset = (page - 1) * perPage; - - const totalItems = await countProposalsByNetwork(chain.network); - const totalPages = Math.ceil(totalItems / perPage); - - if (page > totalPages) { - console.error(`Page ${page} is out of range`); - throw new OutOfRangeError(page); - } - - return { - page, - perPage, - totalItems, - totalPages, - items: await getProposalsList(chain.network, perPage, offset), - }; - } -} diff --git a/src/governance/governance.utils.ts b/src/governance/governance.utils.ts deleted file mode 100644 index 08c4ec0f..00000000 --- a/src/governance/governance.utils.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Network } from '@badger-dao/sdk'; - -import { getDataMapper } from '../aws/dynamodb.utils'; -import { GovernanceProposals } from '../aws/models/governance-proposals.model'; -import { Chain } from '../chains/config/chain.config'; -import { NodataForChainError } from '../errors/allocation/nodata.for.chain.error'; -import { DdbError } from '../errors/internal/ddb.error'; - -export async function getLastProposalUpdateBlock(network: Network) { - const mapper = getDataMapper(); - - try { - for await (const item of mapper.query( - GovernanceProposals, - { network }, - { limit: 1, indexName: 'IndexGovernanceProposalsUpdateBlock', scanIndexForward: false }, - )) { - return item.updateBlock || null; - } - } catch (_) { - return null; - } - - return null; -} - -export async function getProposalByIdx(chain: Chain, proposalId: string) { - const mapper = getDataMapper(); - const timelockAddress = chain.sdk.governance.timelockAddress; - - if (!timelockAddress) { - throw new NodataForChainError(chain.network); - } - - let proposal: GovernanceProposals | undefined; - - try { - for await (const item of mapper.query( - GovernanceProposals, - { idx: GovernanceProposals.genIdx(chain.network, timelockAddress, proposalId) }, - { - limit: 1, - scanIndexForward: false, - }, - )) { - proposal = item; - } - } catch (err) { - console.error(err); - throw new DdbError(`${err}`); - } - - return proposal; -} - -// we can try to use PaginationQuery, but it looks like it does same iterations -// one thing, that it can save some network traffic between app and ddb -export async function countProposalsByNetwork(network: Network) { - const mapper = getDataMapper(); - - let count = 0; - - try { - for await (const _ of mapper.query( - GovernanceProposals, - { network }, - { indexName: 'IndexGovernanceProposalsUpdateBlock' }, - )) { - count++; - } - } catch (err) { - console.error(err); - throw new DdbError(`${err}`); - } - - return count; -} - -export async function getProposalsList(network: Network, limit: number, offset: number) { - const mapper = getDataMapper(); - - const proposals: GovernanceProposals[] = []; - - const innerLimit = limit + offset; - let offsetCounter = 0; - - try { - for await (const item of mapper.query( - GovernanceProposals, - { network }, - { - limit: innerLimit, - indexName: 'IndexGovernanceProposalsUpdateBlock', - scanIndexForward: false, - }, - )) { - if (offsetCounter <= offset && offset !== 0) { - offsetCounter++; - continue; - } - - proposals.push(item); - } - } catch (err) { - console.error(err); - throw new DdbError(`${err}`); - } - - return proposals; -} diff --git a/src/governance/interfaces/governance.proposals.list.ts b/src/governance/interfaces/governance.proposals.list.ts deleted file mode 100644 index a802d976..00000000 --- a/src/governance/interfaces/governance.proposals.list.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { GovernanceProposals } from '../../aws/models/governance-proposals.model'; - -export interface GovernanceProposalsList { - page: number; - perPage: number; - totalItems: number; - totalPages: number; - items: GovernanceProposals[]; -} diff --git a/src/governance/responses/proposal.list.response.ts b/src/governance/responses/proposal.list.response.ts deleted file mode 100644 index 3be2c296..00000000 --- a/src/governance/responses/proposal.list.response.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Description, Example, Property, Title } from '@tsed/schema'; - -import { GovernanceProposals } from '../../aws/models/governance-proposals.model'; -import { GovernanceProposalsList } from '../interfaces/governance.proposals.list'; - -export class ProposalListResponse implements GovernanceProposalsList { - @Title('page') - @Description('current page') - @Example(1) - @Property() - page!: number; - - @Title('perPage') - @Description('items per page') - @Example(10) - @Property() - perPage!: number; - - @Title('totalItems') - @Description('total items') - @Example(50) - @Property() - totalItems!: number; - - @Title('totalPages') - @Description('pages count') - @Example(5) - @Property() - totalPages!: number; - - @Title('items') - @Description('Proposals items') - @Property() - items!: GovernanceProposals[]; -} diff --git a/src/governance/responses/proposal.response.ts b/src/governance/responses/proposal.response.ts deleted file mode 100644 index 85ff1514..00000000 --- a/src/governance/responses/proposal.response.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { Description, Example, Property, Title } from '@tsed/schema'; - -import { GovernanceProposalsChild } from '../../aws/models/governance-proposals-child.interface'; -import { GovernanceProposalsDisputes } from '../../aws/models/governance-proposals-disputes.interface'; -import { GovernanceProposalsStatuses } from '../../aws/models/governance-proposals-statuses.interface'; - -export class ProposalResponse { - @Title('proposalId') - @Description('id of the proposal sequence') - @Example('0xe9bfab585a583ae5cc2395f40bfb61b5c93dee4356079f1c642d7157be8300c8') - @Property() - public proposalId!: string; - - @Title('createdAt') - @Description('time when proposal was indexed') - @Example(new Date().getTime() / 1000) - @Property() - public createdAt!: number; - - @Title('target') - @Description('target address of the proposal') - @Example('0x2260fac5e5542a773aa44fbcfedf7c193bc2c599') - @Property() - public target!: string; - - @Title('value') - @Description('value of the proposal') - @Example(0) - @Property() - public value!: number; - - @Title('callData') - @Description('call data of the proposal to be execute') - @Example('0xc7b9d530000000000000000000000000e8ea1d8b3a5a4cec7e94ae330ff18e82b5d22fa6') - @Property() - public callData!: string; - - @Title('readyTime') - @Description('time when proposal is ready to be executed') - @Example(new Date().getTime() / 1000) - @Property() - public readyTime!: number; - - @Title('sender') - @Description('address of the sender') - @Example('0x2260fac5e5542a773aa44fbcfedf7c193bc2c599') - @Property() - public sender!: string; - - @Title('currentStatus') - @Description('current status of the proposal') - @Example('queued') - @Property() - public currentStatus!: string; - - @Title('statuses') - @Description('status history of the proposal') - @Example([ - Object.assign(new GovernanceProposalsStatuses(), { - name: 'CallExecuted', - sender: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - status: 'Executed', - value: 0, - updatedAt: new Date().getTime() / 1000, - }), - ]) - @Property() - public statuses!: Array; - - @Title('disputes') - @Description('disputes history of the proposal') - @Example([ - Object.assign(new GovernanceProposalsDisputes(), { - name: 'CallDisputed', - ruling: true, - sender: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - status: 'Disputed', - }), - ]) - @Property() - public disputes!: Array; - - @Title('children') - @Description('batched actions or the root proposal') - @Example([ - Object.assign(new GovernanceProposalsChild(), { - index: 4, - value: 0, - callData: '0xc7b9d530000000000000000000000000e8ea1d8b3a5a4cec7e94ae330ff18e82b5d22fa6', - target: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - predecessor: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - sender: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - executed: Object.assign(new GovernanceProposalsStatuses(), { - name: 'CallExecuted', - sender: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - status: 'Executed', - value: 0, - updatedAt: new Date().getTime() / 1000, - }), - }), - ]) - @Property() - public children!: Array; -} diff --git a/src/indexers/accounts-indexer.ts b/src/indexers/accounts-indexer.ts index 3529813a..977c173f 100644 --- a/src/indexers/accounts-indexer.ts +++ b/src/indexers/accounts-indexer.ts @@ -73,7 +73,7 @@ export async function refreshClaimableBalances(chain: Chain) { } export async function refreshUserAccounts() { - const chains = getSupportedChains().filter((c) => c.network !== Network.BinanceSmartChain); + const chains = getSupportedChains([Network.Ethereum]); await Promise.all( chains.map(async (chain) => { try { diff --git a/src/indexers/apy-snapshots-indexer.ts b/src/indexers/apy-snapshots-indexer.ts index e6ef1415..89ad866b 100644 --- a/src/indexers/apy-snapshots-indexer.ts +++ b/src/indexers/apy-snapshots-indexer.ts @@ -1,3 +1,5 @@ +import { Network } from '@badger-dao/sdk'; + import { getDataMapper } from '../aws/dynamodb.utils'; import { CachedYieldSource } from '../aws/models/cached-yield-source.interface'; import { VaultDefinitionModel } from '../aws/models/vault-definition.model'; @@ -7,7 +9,7 @@ import { rfw } from '../utils/retry.utils'; import { getVaultPerformance, queryYieldSources } from '../vaults/vaults.utils'; export async function refreshApySnapshots() { - for (const chain of getSupportedChains()) { + for (const chain of getSupportedChains([Network.Ethereum])) { const vaults = await chain.vaults.all(); await Promise.all(vaults.map(async (vault) => refreshChainApySnapshots(chain, vault))); } diff --git a/src/indexers/constants/scan.constants.ts b/src/indexers/constants/scan.constants.ts new file mode 100644 index 00000000..3c6186d6 --- /dev/null +++ b/src/indexers/constants/scan.constants.ts @@ -0,0 +1 @@ +export const MAX_SCAN_RANGE = 300_000; diff --git a/src/indexers/governance-proposals-indexer.ts b/src/indexers/governance-proposals-indexer.ts deleted file mode 100644 index 2fec7980..00000000 --- a/src/indexers/governance-proposals-indexer.ts +++ /dev/null @@ -1,411 +0,0 @@ -import { DataMapper } from '@aws/dynamodb-data-mapper'; -import { - CallDisputedEvent, - CallDisputedResolvedEvent, - CallExecutedEvent, - CallScheduledEvent, - CancelledEvent, -} from '@badger-dao/sdk/lib/contracts/TimelockController'; -import { GovernanceProxyMock } from '@badger-dao/sdk/lib/governance/mocks/governance.proxy.mock'; - -import { getDataMapper } from '../aws/dynamodb.utils'; -import { GovernanceProposals } from '../aws/models/governance-proposals.model'; -import { GovernanceProposalsChild } from '../aws/models/governance-proposals-child.interface'; -import { GovernanceProposalsDisputes } from '../aws/models/governance-proposals-disputes.interface'; -import { GovernanceProposalsStatuses } from '../aws/models/governance-proposals-statuses.interface'; -import { getSupportedChains } from '../chains/chains.utils'; -import { Chain } from '../chains/config/chain.config'; -import { PRODUCTION } from '../config/constants'; -import { getLastProposalUpdateBlock } from '../governance/governance.utils'; - -export async function updateGovernanceProposals() { - if (PRODUCTION) { - console.info('Governance proposals not rdy for production, skipping'); - return; - } - - console.info('Updating governance proposals started'); - - const mapper = getDataMapper(); - - for (const chain of getSupportedChains()) { - const timelockAddress = chain.sdk.governance.timelockAddress; - - await chain.sdk.ready(); - - if (!timelockAddress) { - console.info(`No timelock address for ${chain.network}, skipping`); - continue; - } - - const lastScannedBlock = await getLastProposalUpdateBlock(chain.network); - - // nit: there is sense to expose this as a method in sdk, wo any proxies - const governanceProxy = new GovernanceProxyMock(chain.sdk); - - const scanRangeOpts = { - startBlock: 0, - endBlock: 0, - }; - - await governanceProxy.processEventsScanRangePr(timelockAddress, scanRangeOpts); - - if (lastScannedBlock) { - scanRangeOpts.startBlock = lastScannedBlock + 1; - } - - const proposalsCreated = await chain.sdk.governance.loadScheduledProposals(scanRangeOpts); - const proposalsStatusesChanged = await chain.sdk.governance.loadProposalsStatusChange(scanRangeOpts); - const proposalsDisputed = await chain.sdk.governance.loadProposalsDisputes(scanRangeOpts); - - if (proposalsCreated.length === 0 && proposalsStatusesChanged.length === 0 && proposalsDisputed.length === 0) { - console.info(`No new proposals for ${chain.network}`); - continue; - } - - const updatedProposalsStatuses: (CallExecutedEvent | CancelledEvent)[] = []; - const updatedProposalsDisputes: (CallDisputedEvent | CallDisputedResolvedEvent)[] = []; - - // save new created proposals - const updatedProposals: GovernanceProposals[] = []; - - for (const proposal of proposalsCreated) { - const isBatchChild = proposal.args.index.toNumber() > 0; - - // We have 2 types of proposals: Single and Batch - // Single(Relative) proposal is a proposal that has only one transaction (target, callData, value) - // Batch(Relative+Children) proposal is a proposal that has more than one transaction(action), still they share same id, - // but they have different index and different target, callData, value - // For sake of simplicity we save batch proposals as children of the main proposal with index 0 - if (!isBatchChild) { - await saveRelativeProposal( - chain, - timelockAddress, - proposal, - proposalsStatusesChanged, - proposalsDisputed, - updatedProposals, - updatedProposalsStatuses, - updatedProposalsDisputes, - ); - } else { - await saveChildProposal( - chain, - mapper, - timelockAddress, - proposal, - proposalsStatusesChanged, - updatedProposals, - updatedProposalsStatuses, - ); - } - } - - try { - if (updatedProposals.length > 0) { - for await (const _ of mapper.batchPut(updatedProposals)) { - } - } - } catch (err) { - console.error({ message: 'Unable to save governance proposals', err }); - } - - // update proposals statuses and disputes - const statusesToUpdate = proposalsStatusesChanged.filter((e) => !updatedProposalsStatuses.includes(e)); - const disputesToUpdate = proposalsDisputed.filter((e) => !updatedProposalsDisputes.includes(e)); - - if (statusesToUpdate.length === 0 && disputesToUpdate.length === 0) { - console.info(`No new statuses or disputes for ${chain.network}`); - continue; - } - - for (const status of statusesToUpdate) { - let proposal!: GovernanceProposals; - const proposalDdbIdx = GovernanceProposals.genIdx(chain.network, timelockAddress, status.args.id); - - try { - proposal = await mapper.get( - Object.assign(new GovernanceProposals(), { - idx: proposalDdbIdx, - }), - ); - } catch (err) { - console.error({ message: `Unable to find proposal ${proposalDdbIdx} to update`, err }); - continue; - } - - if (proposal.statuses.find((s) => s.transactionHash === status.transactionHash)) { - continue; - } - - const block = await status.getBlock(); - - const proposalStatus = Object.assign(new GovernanceProposalsStatuses(), { - name: status.event, - sender: status.args.sender, - status: status.args.status, - transactionHash: status.transactionHash, - blockNumber: block.number, - updatedAt: block.timestamp, - }); - - if (status.event === 'CallExecuted') { - proposalStatus.value = (status).args.value.toNumber(); - - if ((status).args.index.toNumber() === 0) { - proposal.statuses.push(proposalStatus); - } else { - const child = proposal.children.find((c) => c.index === (status).args.index.toNumber()); - if (!child) { - console.error({ - message: `Unable to find child ${(( - status - )).args.index.toNumber()} proposal ${proposalDdbIdx} to update`, - }); - continue; - } - child.executed = proposalStatus; - } - } else { - proposal.statuses.push(proposalStatus); - } - - proposal.currentStatus = status.args.status; - proposal.updateBlock = block.number; - - try { - await mapper.put(proposal); - } catch (err) { - console.error({ message: `Unable to save governance proposal ${proposalDdbIdx}`, err }); - } - - console.info(`New status ${status.transactionHash} for proposal ${proposalDdbIdx} added`); - } - - for (const dispute of disputesToUpdate) { - let proposal!: GovernanceProposals; - const proposalDdbIdx = GovernanceProposals.genIdx(chain.network, timelockAddress, dispute.args.id); - - try { - proposal = await mapper.get( - Object.assign(new GovernanceProposals(), { - idx: proposalDdbIdx, - }), - ); - } catch (err) { - console.error({ message: `Unable to find proposal ${proposalDdbIdx} to update`, err }); - continue; - } - - if (proposal.disputes.find((d) => d.transactionHash === dispute.transactionHash)) { - continue; - } - - const block = await dispute.getBlock(); - - const proposalDispute = Object.assign(new GovernanceProposalsDisputes(), { - name: dispute.event, - ruling: dispute.event === 'CallDisputedResolved' ? (dispute).args.ruling : null, - sender: dispute.args.sender, - status: dispute.args.status, - transactionHash: dispute.transactionHash, - blockNumber: block.number, - updatedAt: block.timestamp, - }); - - proposal.disputes.push(proposalDispute); - - proposal.currentStatus = dispute.args.status; - proposal.updateBlock = block.number; - - try { - await mapper.put(proposal); - } catch (err) { - console.error({ message: `Unable to save governance proposal ${proposalDdbIdx}`, err }); - } - - console.info(`New dispute ${dispute.transactionHash} for proposal ${proposalDdbIdx} added`); - } - } - - console.info('Updating governance proposals ended'); -} - -async function saveRelativeProposal( - chain: Chain, - timelockAddress: string, - proposal: CallScheduledEvent, - proposalsStatusesChanged: (CallExecutedEvent | CancelledEvent)[], - proposalsDisputed: (CallDisputedEvent | CallDisputedResolvedEvent)[], - updatedProposals: GovernanceProposals[], - updatedProposalsStatuses: (CallExecutedEvent | CancelledEvent)[], - updatedProposalsDisputes: (CallDisputedEvent | CallDisputedResolvedEvent)[], -) { - let latestEvent!: GovernanceProposalsStatuses | GovernanceProposalsDisputes; - - const block = await proposal.getBlock(); - - const proposalsStatuses = await Promise.all( - proposalsStatusesChanged - .filter((e) => { - return ( - e.args.id === proposal.args.id || - (e.args.id === proposal.args.id && - e.event === 'CallExecuted' && - (e).args.index.toNumber() === 0) - ); - }) - .map(async (e) => { - const block = await e.getBlock(); - - updatedProposalsStatuses.push(e); - - const proposalStatus = Object.assign(new GovernanceProposalsStatuses(), { - name: e.event, - sender: e.args.sender, - status: e.args.status, - transactionHash: e.transactionHash, - blockNumber: block.number, - updatedAt: block.timestamp, - }); - - if (e.event === 'CallExecuted') { - proposalStatus.value = (e).args.value.toNumber(); - } - - if (!latestEvent || block.number > (latestEvent && latestEvent?.blockNumber)) { - latestEvent = proposalStatus; - } - - return proposalStatus; - }), - ); - - const proposalsDisputes = await Promise.all( - proposalsDisputed - .filter((e) => e.args.id === proposal.args.id) - .map(async (e) => { - const block = await e.getBlock(); - - updatedProposalsDisputes.push(e); - - const proposalDispute = Object.assign(new GovernanceProposalsDisputes(), { - name: e.event, - ruling: e.event === 'CallDisputedResolved' ? (e).args.ruling : null, - sender: e.args.sender, - status: e.args.status, - transactionHash: e.transactionHash, - blockNumber: block.number, - updatedAt: block.timestamp, - }); - - if (!latestEvent || block.number > (latestEvent && latestEvent?.blockNumber)) { - latestEvent = proposalDispute; - } - - return proposalDispute; - }), - ); - - const proposalDdbIdx = GovernanceProposals.genIdx(chain.network, timelockAddress, proposal.args.id); - - updatedProposals.push( - Object.assign(new GovernanceProposals(), { - idx: proposalDdbIdx, - proposalId: proposal.args.id, - network: chain.network, - createdAt: Date.now() / 1000, - contractAddr: timelockAddress, - targetAddr: proposal.args.target, - value: proposal.args.value.toNumber(), - callData: proposal.args.data, - readyTime: proposal.args.readyTime.toNumber(), - sender: proposal.args.sender, - currentStatus: !latestEvent ? proposal.args.status : latestEvent.status, - creationBlock: block.number, - updateBlock: !latestEvent ? block.number : latestEvent.blockNumber, - statuses: proposalsStatuses, - disputes: proposalsDisputes, - children: [], - }), - ); - - console.info( - `New proposal ${proposalDdbIdx} with ${proposalsStatuses.length} - statuses and ${proposalsDisputes.length} disputes added`, - ); -} - -async function saveChildProposal( - chain: Chain, - mapper: DataMapper, - timelockAddress: string, - proposal: CallScheduledEvent, - proposalsStatusesChanged: (CallExecutedEvent | CancelledEvent)[], - updatedProposals: GovernanceProposals[], - updatedProposalsStatuses: (CallExecutedEvent | CancelledEvent)[], -) { - let relativeFromDdb = false; - let relativeProposal: GovernanceProposals | undefined; - - if (updatedProposals.length > 0) { - relativeProposal = updatedProposals.find((p) => p.proposalId === proposal.args.id); - } - - if (!relativeProposal) { - try { - const proposalDdbIdx = GovernanceProposals.genIdx(chain.network, timelockAddress, proposal.args.id); - relativeProposal = await mapper.get(Object.assign(new GovernanceProposals(), { idx: proposalDdbIdx })); - relativeFromDdb = true; - } catch (err) { - console.error({ message: `Unable to find proposal ${proposal.args.id} to update`, err }); - return; - } - } - - const executedStatusEvent = proposalsStatusesChanged.find((e) => { - return ( - e.args.id === proposal.args.id && - e.event === 'CallExecuted' && - (e).args.index.toNumber() === proposal.args.index.toNumber() - ); - }); - - const childProposal = Object.assign(new GovernanceProposalsChild(), { - index: proposal.args.index.toNumber(), - value: proposal.args.value.toNumber(), - callData: proposal.args.data, - sender: proposal.args.sender, - targetAddr: proposal.args.target, - predecessor: proposal.args.predecessor, - }); - - if (executedStatusEvent) { - const block = await executedStatusEvent.getBlock(); - - updatedProposalsStatuses.push(executedStatusEvent); - - childProposal.executed = Object.assign(new GovernanceProposalsStatuses(), { - name: executedStatusEvent.event, - sender: executedStatusEvent.args.sender, - status: executedStatusEvent.args.status, - transactionHash: executedStatusEvent.transactionHash, - blockNumber: block.number, - updatedAt: block.timestamp, - }); - - if (executedStatusEvent.event === 'CallExecuted') { - childProposal.executed.value = (executedStatusEvent).args.index.toNumber(); - } - } - - if (relativeProposal.children) { - relativeProposal.children.push(childProposal); - } else { - relativeProposal.children = [childProposal]; - } - - if (relativeFromDdb) updatedProposals.push(relativeProposal); - - console.info(`New child proposal ${proposal.args.index} for ${relativeProposal.idx} added`); -} diff --git a/src/indexers/interfaces/last-scanned-block-meta.interface.ts b/src/indexers/interfaces/last-scanned-block-meta.interface.ts new file mode 100644 index 00000000..3ce66bef --- /dev/null +++ b/src/indexers/interfaces/last-scanned-block-meta.interface.ts @@ -0,0 +1,7 @@ +import { Network } from '@badger-dao/sdk/lib/config/enums/network.enum'; + +export interface LastScannedBlock { + lastScannedBlock: number; +} + +export type LastScannedBlockMeta = Record>; diff --git a/src/indexers/leaderboards-indexer.ts b/src/indexers/leaderboards-indexer.ts index e553d696..50883149 100644 --- a/src/indexers/leaderboards-indexer.ts +++ b/src/indexers/leaderboards-indexer.ts @@ -1,4 +1,4 @@ -import { BadgerType, BadgerTypeMap } from '@badger-dao/sdk'; +import { BadgerType, BadgerTypeMap, Network } from '@badger-dao/sdk'; import { ethers } from 'ethers'; import { getDataMapper, getLeaderboardKey } from '../aws/dynamodb.utils'; @@ -10,7 +10,7 @@ import { Chain } from '../chains/config/chain.config'; import { getBadgerType } from '../leaderboards/leaderboards.utils'; export async function indexBoostLeaderBoard() { - for (const chain of getSupportedChains()) { + for (const chain of getSupportedChains([Network.Ethereum])) { const chainResults = await generateChainBoostsLeaderBoard(chain); const summary: BadgerTypeMap = { [BadgerType.Basic]: 0, diff --git a/src/indexers/prices-indexer.ts b/src/indexers/prices-indexer.ts index 35a3509d..ba57bc12 100644 --- a/src/indexers/prices-indexer.ts +++ b/src/indexers/prices-indexer.ts @@ -1,3 +1,5 @@ +import { Network } from '@badger-dao/sdk'; + import { getSupportedChains } from '../chains/chains.utils'; import { Chain } from '../chains/config/chain.config'; import { PricingType } from '../prices/enums/pricing-type.enum'; @@ -7,7 +9,7 @@ import { lookUpAddrByTokenName } from '../tokens/tokens.utils'; import { rfw } from '../utils/retry.utils'; export async function indexPrices() { - for (const chain of getSupportedChains()) { + for (const chain of getSupportedChains([Network.Ethereum])) { try { const { tokens } = chain; const chainTokens = Object.entries(tokens).map((e) => ({ diff --git a/src/indexers/protocol-metric-indexer.ts b/src/indexers/protocol-metric-indexer.ts index 374a2e74..74af91b4 100644 --- a/src/indexers/protocol-metric-indexer.ts +++ b/src/indexers/protocol-metric-indexer.ts @@ -1,3 +1,5 @@ +import { Network } from '@badger-dao/sdk'; + import { getDataMapper } from '../aws/dynamodb.utils'; import { ProtocolMetricSnapshot } from '../aws/models/protocol-metric-snapshot.model'; import { getSupportedChains } from '../chains/chains.utils'; @@ -7,7 +9,7 @@ import { rfw } from '../utils/retry.utils'; export const indexProtocolMetrics = async () => { const mapper = getDataMapper(); - const metric = await rfw(getChainMetrics)(getSupportedChains()); + const metric = await rfw(getChainMetrics)(getSupportedChains([Network.Ethereum])); const metricSnapshot = Object.assign(new ProtocolMetricSnapshot(), { ...metric, type: MetricType.Protocol }); try { diff --git a/src/indexers/vault-balances-indexer.ts b/src/indexers/vault-balances-indexer.ts index e71c9786..67edc921 100644 --- a/src/indexers/vault-balances-indexer.ts +++ b/src/indexers/vault-balances-indexer.ts @@ -1,4 +1,4 @@ -import { Protocol } from '@badger-dao/sdk'; +import { Network, Protocol } from '@badger-dao/sdk'; import { getDataMapper, getVaultEntityId } from '../aws/dynamodb.utils'; import { VaultDefinitionModel } from '../aws/models/vault-definition.model'; @@ -13,7 +13,7 @@ import { rfw } from '../utils/retry.utils'; import { getCachedVault } from '../vaults/vaults.utils'; export async function refreshVaultBalances() { - for (const chain of getSupportedChains()) { + for (const chain of getSupportedChains([Network.Ethereum])) { const vaults = await chain.vaults.all(); await Promise.all(vaults.map(async (v) => updateVaultTokenBalances(chain, v))); } diff --git a/src/indexers/vault-definition-indexer.ts b/src/indexers/vault-definition-indexer.ts index c2a50b6a..1310c5cf 100644 --- a/src/indexers/vault-definition-indexer.ts +++ b/src/indexers/vault-definition-indexer.ts @@ -1,4 +1,4 @@ -import { RegistryVault } from '@badger-dao/sdk'; +import { Network, RegistryVault } from '@badger-dao/sdk'; import { getDataMapper } from '../aws/dynamodb.utils'; import { VaultDefinitionModel } from '../aws/models/vault-definition.model'; @@ -8,7 +8,7 @@ import { rfw } from '../utils/retry.utils'; import { constructVaultDefinition } from './indexer.utils'; export async function captureVaultData() { - const chains = getSupportedChains(); + const chains = getSupportedChains([Network.Ethereum]); for (const chain of chains) { const sdk = await chain.getSdk(); diff --git a/src/indexers/vault-harvests-indexer.ts b/src/indexers/vault-harvests-indexer.ts index b95feaec..3bf00e8f 100644 --- a/src/indexers/vault-harvests-indexer.ts +++ b/src/indexers/vault-harvests-indexer.ts @@ -1,3 +1,5 @@ +import { Network } from '@badger-dao/sdk'; + import { getDataMapper, getVaultEntityId } from '../aws/dynamodb.utils'; import { VaultYieldEvent } from '../aws/models/vault-yield-event.model'; import { getSupportedChains } from '../chains/chains.utils'; @@ -5,7 +7,7 @@ import { rfw } from '../utils/retry.utils'; import { HARVEST_SCAN_BLOCK_INCREMENT, loadYieldEvents } from '../vaults/harvests.utils'; export async function updateVaultHarvests() { - const chains = getSupportedChains(); + const chains = getSupportedChains([Network.Ethereum]); const mapper = getDataMapper(); for (const chain of chains) { diff --git a/src/indexers/vault-snapshots-indexer.ts b/src/indexers/vault-snapshots-indexer.ts index 8ad6ff08..ef5ef3b9 100644 --- a/src/indexers/vault-snapshots-indexer.ts +++ b/src/indexers/vault-snapshots-indexer.ts @@ -1,3 +1,5 @@ +import { Network } from '@badger-dao/sdk'; + import { getDataMapper, getVaultEntityId } from '../aws/dynamodb.utils'; import { CurrentVaultSnapshotModel } from '../aws/models/current-vault-snapshot.model'; import { HistoricVaultSnapshotModel } from '../aws/models/historic-vault-snapshot.model'; @@ -10,7 +12,7 @@ export async function refreshVaultSnapshots() { const timestamp = Date.now(); const mapper = getDataMapper(); - for (const chain of getSupportedChains()) { + for (const chain of getSupportedChains([Network.Ethereum])) { const vaults = await rfw(chain.vaults.all, chain.vaults)(); await Promise.all( vaults.map(async (vault) => { diff --git a/src/indexers/yield-estimates-indexer.ts b/src/indexers/yield-estimates-indexer.ts index c535993c..b78d85b5 100644 --- a/src/indexers/yield-estimates-indexer.ts +++ b/src/indexers/yield-estimates-indexer.ts @@ -1,4 +1,4 @@ -import BadgerSDK, { ONE_DAY_MS, TokenBalance, VaultState, VaultVersion } from '@badger-dao/sdk'; +import BadgerSDK, { Network, ONE_DAY_MS, TokenBalance, VaultState, VaultVersion } from '@badger-dao/sdk'; import { BadgerTreeDistribution_OrderBy, OrderDirection, @@ -114,7 +114,7 @@ async function captureYieldEstimate(chain: Chain, vault: VaultDefinitionModel, n } export async function refreshYieldEstimates() { - const chains = getSupportedChains(); + const chains = getSupportedChains([Network.Ethereum]); const now = Date.now(); for (const chain of chains) { diff --git a/yarn.lock b/yarn.lock index 93c858ed..68d6de88 100644 --- a/yarn.lock +++ b/yarn.lock @@ -796,10 +796,10 @@ "@babel/helper-validator-identifier" "^7.18.6" to-fast-properties "^2.0.0" -"@badger-dao/sdk-mocks@^1.18.13": - version "1.18.13" - resolved "https://registry.yarnpkg.com/@badger-dao/sdk-mocks/-/sdk-mocks-1.18.13.tgz#0c78db2758e94a1b6a007a679397dc1c6a8e54f8" - integrity sha512-f2K9rYrxnP1XHcLwMOKmPKY0pHZHQ2e9blM9CWTFIS7G0sJi+1HPt7gUyv8jbiqozFWkZjIOEHmXfUOHt1oLvA== +"@badger-dao/sdk-mocks@^1.23.0": + version "1.23.0" + resolved "https://registry.yarnpkg.com/@badger-dao/sdk-mocks/-/sdk-mocks-1.23.0.tgz#e2d7997b7d58f017c4beb4c052e1f3e169903d29" + integrity sha512-zJOlorTL7lEUgOsODecUgZKlhZ2ibm3zXbJvlXoIBTUmIGnyOxNl/f32aBI8QOOJctaCQXc0YrRs9T3MonhQuQ== dependencies: "@types/jest" "27.0.2" "@typescript-eslint/eslint-plugin" "5.0.0" @@ -814,21 +814,22 @@ jest "27.3.1" prettier "2.4.1" pretty-quick "3.1.3" - semantic-release "19.0.2" + semantic-release "19.0.3" ts-jest "27.0.7" ts-node "^10.9.1" tslib "2.3.1" typescript "4.5.4" -"@badger-dao/sdk@^1.19.1": - version "1.19.1" - resolved "https://registry.yarnpkg.com/@badger-dao/sdk/-/sdk-1.19.1.tgz#faa46d280661e8ade1b09963b4d85b1d3ce67bbb" - integrity sha512-Dqib7gA9VQHTnMBzAX5x+045EAtVfBilj+k9Wb/CVLGFjHrPQgasZuEMTLFaj9GScdLhukcsDgBBZv8KjP2+mA== +"@badger-dao/sdk@^1.23.0": + version "1.23.0" + resolved "https://registry.yarnpkg.com/@badger-dao/sdk/-/sdk-1.23.0.tgz#d7d7bc548d6b9e53ea8cd70d08b99513b7cb24bc" + integrity sha512-+HIu56IxJPazSU6nxRArF29IDU8xJ2lseJK1kbqiXNELBqU0rL1EvsVklsFuEFn9T3LYlF8nwa4PWqjLUcDDfQ== dependencies: "@0xsequence/indexer" "^0.40.6" "@0xsequence/multicall" "^0.40.6" "@0xsequence/provider" "^0.40.6" "@0xsequence/relayer" "^0.40.6" + "@types/mkdirp" "^1.0.2" axios "^0.24.0" ethers "^5.5.2" graphql "^16.5.0" @@ -883,7 +884,7 @@ "@ethereumjs/common" "^2.6.4" ethereumjs-util "^7.1.5" -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.6.3", "@ethersproject/abi@^5.7.0": +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.0", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.6.3", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== @@ -898,7 +899,7 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.0.0", "@ethersproject/abstract-provider@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== @@ -922,7 +923,7 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.0.0", "@ethersproject/address@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== @@ -948,7 +949,7 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.0.0", "@ethersproject/bignumber@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== @@ -957,7 +958,7 @@ "@ethersproject/logger" "^5.7.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.5.0", "@ethersproject/bytes@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== @@ -971,7 +972,7 @@ dependencies: "@ethersproject/bignumber" "^5.7.0" -"@ethersproject/contracts@5.7.0": +"@ethersproject/contracts@5.7.0", "@ethersproject/contracts@^5.0.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== @@ -3582,6 +3583,13 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== +"@types/mkdirp@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-1.0.2.tgz#8d0bad7aa793abe551860be1f7ae7f3198c16666" + integrity sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ== + dependencies: + "@types/node" "*" + "@types/multer@^1.4.5": version "1.4.7" resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.7.tgz#89cf03547c28c7bbcc726f029e2a76a7232cc79e" @@ -6062,9 +6070,9 @@ decimal.js@^10.2.1: integrity sha512-Nv6ENEzyPQ6AItkGwLE2PGKinZZ9g59vSh2BeH6NqPu0OTKZ5ruJsVqh/orbAnqXc9pBbgXAIrc2EyaCj8NpGg== decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== decompress-response@^3.2.0, decompress-response@^3.3.0: version "3.3.0" @@ -7092,6 +7100,18 @@ ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: ethereum-cryptography "^0.1.3" rlp "^2.2.4" +ethers-proxies@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ethers-proxies/-/ethers-proxies-1.0.0.tgz#9a799ceb798d19216bf104a6ca528ad6d4e39f41" + integrity sha512-f91VHS2mxQVqFjvaOtixJUPH4O2Q3x2v5xX5Zy6hiWEcPSf4/zJ4PkrG9eNqLJAmwEM93qKNVtQuN+bZoFmQqQ== + dependencies: + "@ethersproject/abi" "^5.0.0" + "@ethersproject/abstract-provider" "^5.0.0" + "@ethersproject/address" "^5.0.0" + "@ethersproject/bignumber" "^5.0.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/contracts" "^5.0.0" + ethers@^5.5.2: version "5.7.0" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.0.tgz#0055da174b9e076b242b8282638bc94e04b39835" @@ -13360,10 +13380,10 @@ seek-bzip@^1.0.5: dependencies: commander "^2.8.1" -semantic-release@19.0.2: - version "19.0.2" - resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-19.0.2.tgz#6011683c06d7b416e5faa5a3f43b22bbf3798aa8" - integrity sha512-7tPonjZxukKECmClhsfyMKDt0GR38feIC2HxgyYaBi+9tDySBLjK/zYDLhh+m6yjnHIJa9eBTKYE7k63ZQcYbw== +semantic-release@19.0.3: + version "19.0.3" + resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-19.0.3.tgz#9291053ad9890052f28e7c5921d4741530d516fd" + integrity sha512-HaFbydST1cDKZHuFZxB8DTrBLJVK/AnDExpK0s3EqLIAAUAHUgnd+VSJCUtTYQKkAkauL8G9CucODrVCc7BuAA== dependencies: "@semantic-release/commit-analyzer" "^9.0.2" "@semantic-release/error" "^3.0.0" @@ -13774,9 +13794,9 @@ socket.io-client@^2.3.0: to-array "0.1.4" socket.io-parser@~3.3.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.2.tgz#ef872009d0adcf704f2fbe830191a14752ad50b6" - integrity sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg== + version "3.3.3" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.3.tgz#3a8b84823eba87f3f7624e64a8aaab6d6318a72f" + integrity sha512-qOg87q1PMWWTeO01768Yh9ogn7chB9zkKtQnya41Y355S0UmpXgpcrFwAgjYJxu9BdKug5r5e9YtVSeWhKBUZg== dependencies: component-emitter "~1.3.0" debug "~3.1.0"