Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implicitly Existential: Add noImplicitAny to TypeScript config, fix related issues #330

Merged
merged 26 commits into from
Oct 15, 2021
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1488eba
Specify a couple of reduce types to avoid anys
Shadowfiend Oct 13, 2021
4c4711a
Add a few type packages
Shadowfiend Oct 13, 2021
38a5ace
Drop unused state/db/migration templates
Shadowfiend Oct 13, 2021
1da3e45
Move logger.ts anys to unknowns
Shadowfiend Oct 13, 2021
898377f
Improve typing for prices.ts getEthereumTokenPrices
Shadowfiend Oct 13, 2021
9e4e350
Ensure convertToEth can also take bigints directly
Shadowfiend Oct 13, 2021
a409b10
Specify reduxCache middleware type
Shadowfiend Oct 13, 2021
bf11816
Introduce a unified ActivityItem type for the UI
Shadowfiend Oct 13, 2021
b62362f
Specify get*State selector types
Shadowfiend Oct 13, 2021
b629bb6
Declare React event types in handlers
Shadowfiend Oct 13, 2021
2fdd13d
Clean up background async thunk typing
Shadowfiend Oct 13, 2021
1e1f46f
Adjust asset transfer schema validation to avoid anys
Shadowfiend Oct 13, 2021
01269a6
Drop a type for placeholder data that is no longer relevant
Shadowfiend Oct 13, 2021
50238cc
Type a couple of redux hooks
Shadowfiend Oct 13, 2021
fe9ebe9
Fix a couple of test types that are resolved as implicit any
Shadowfiend Oct 13, 2021
931c44c
Tighten type guards for account/timestamp activities
Shadowfiend Oct 13, 2021
eac69e9
Fix up typing in webpack config
Shadowfiend Oct 13, 2021
52710db
Add typing for the renameAndPickKeys helper
Shadowfiend Oct 13, 2021
a14fb41
checkIfPlausibleETHAddress now has a type for its parameter!
Shadowfiend Oct 13, 2021
107f42b
Deal with Coingecko price validator's loose JDT typing
Shadowfiend Oct 13, 2021
c54ccec
Enable noImplicitAny in tsconfig
Shadowfiend Oct 13, 2021
4c7d2ed
Include Alchemy JSON validation errors when warning about failure
Shadowfiend Oct 13, 2021
0df26e3
Use Tally logger in alchemy.ts
Shadowfiend Oct 13, 2021
91561bd
Avoid an error with long-decimal token prices
Shadowfiend Oct 13, 2021
ff7679e
Merge remote-tracking branch 'origin/main' into implicitly-existential
Shadowfiend Oct 15, 2021
813666d
Merge branch 'main' into implicitly-existential
mhluongo Oct 15, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion background/constants/currencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ export const BTC = {

export const BASE_ASSETS = [ETH, BTC]

export const BASE_ASSETS_BY_SYMBOL = BASE_ASSETS.reduce((acc, asset) => {
export const BASE_ASSETS_BY_SYMBOL = BASE_ASSETS.reduce<{
[assetSymbol: string]: FungibleAsset
}>((acc, asset) => {
const newAcc = {
...acc,
}
Expand Down
52 changes: 0 additions & 52 deletions background/constants/default-state.ts

This file was deleted.

67 changes: 41 additions & 26 deletions background/lib/alchemy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import {
AlchemyProvider,
AlchemyWebSocketProvider,
} from "@ethersproject/providers"
import { logger, utils } from "ethers"
import { utils } from "ethers"

import logger from "./logger"
import { AssetTransfer, HexString, SmartContractFungibleAsset } from "../types"
import { ETH, ETHEREUM } from "../constants"

Expand Down Expand Up @@ -36,10 +37,20 @@ const alchemyAssetTransferJTD = {
additionalProperties: true,
} as const

type AlchemyAssetTransferResponse = JTDDataType<typeof alchemyAssetTransferJTD>
const alchemyGetAssetTransfersJTD = {
properties: {
transfers: {
elements: alchemyAssetTransferJTD,
},
},
} as const

type AlchemyAssetTransferResponse = JTDDataType<
typeof alchemyGetAssetTransfersJTD
>

const isValidAlchemyAssetTransferResponse =
ajv.compile<AlchemyAssetTransferResponse>(alchemyAssetTransferJTD)
ajv.compile<AlchemyAssetTransferResponse>(alchemyGetAssetTransfersJTD)

/**
* Use Alchemy's getAssetTransfers call to get historical transfers for an
Expand Down Expand Up @@ -82,51 +93,54 @@ export async function getAssetTransfers(
]),
])

return rpcResponses[0].transfers
.concat(rpcResponses[1].transfers)
.map((json: unknown) => {
if (!isValidAlchemyAssetTransferResponse(json)) {
logger.warn(
"Alchemy asset transfer response didn't validate, did the API change?",
json
)
return null
return rpcResponses
.flatMap((jsonResponse: unknown) => {
if (isValidAlchemyAssetTransferResponse(jsonResponse)) {
return jsonResponse.transfers
}

logger.warn(
"Alchemy asset transfer response didn't validate, did the API change?",
jsonResponse,
isValidAlchemyAssetTransferResponse.errors
)
return []
})
.map((transfer) => {
// TODO handle NFT asset lookup properly
if (json.erc721TokenId) {
if (transfer.erc721TokenId) {
return null
}

// we don't care about 0-value transfers
// TODO handle nonfungible assets properly
// TODO handle assets with a contract address and no name
if (
!json.rawContract ||
!json.rawContract.value ||
!json.rawContract.decimal ||
!json.asset
!transfer.rawContract ||
!transfer.rawContract.value ||
!transfer.rawContract.decimal ||
!transfer.asset
) {
return null
}

const asset = !json.rawContract.address
const asset = !transfer.rawContract.address
? {
contractAddress: json.rawContract.address,
decimals: Number(BigInt(json.rawContract.decimal)),
symbol: json.asset,
contractAddress: transfer.rawContract.address,
decimals: Number(BigInt(transfer.rawContract.decimal)),
symbol: transfer.asset,
homeNetwork: ETHEREUM, // TODO is this true?
}
: ETH
return {
network: ETHEREUM, // TODO make this friendly across other networks
assetAmount: {
asset,
amount: BigInt(json.rawContract.value),
amount: BigInt(transfer.rawContract.value),
},
txHash: json.hash,
to: json.to,
from: json.from,
txHash: transfer.hash,
to: transfer.to,
from: transfer.from,
dataSource: "alchemy",
} as AssetTransfer
})
Expand Down Expand Up @@ -182,7 +196,8 @@ export async function getTokenBalances(
if (!isValidAlchemyTokenBalanceResponse(json)) {
logger.warn(
"Alchemy token balance response didn't validate, did the API change?",
json
json,
isValidAlchemyTokenBalanceResponse.errors
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

)
return []
}
Expand Down
11 changes: 0 additions & 11 deletions background/lib/db.ts

This file was deleted.

4 changes: 3 additions & 1 deletion background/lib/erc20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ export async function getBalances(
tokens.map((t) => t.contractAddress)
)

const assetByAddress = tokens.reduce((acc, asset) => {
const assetByAddress = tokens.reduce<{
[contractAddress: string]: SmartContractFungibleAsset
}>((acc, asset) => {
const newAcc = { ...acc }
newAcc[asset.contractAddress.toLowerCase()] = asset
return newAcc
Expand Down
10 changes: 5 additions & 5 deletions background/lib/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ enum LogLevel {
error = "error",
}

function genericLogger(level: LogLevel, input: any[]) {
function genericLogger(level: LogLevel, input: unknown[]) {
console[level](...input)

const stackTrace = new Error().stack.split("\n").filter((line) => {
Expand All @@ -29,19 +29,19 @@ function genericLogger(level: LogLevel, input: any[]) {
}

const logger = {
log(...input: any[]) {
log(...input: unknown[]): void {
genericLogger(LogLevel.log, input)
},

info(...input: any[]) {
info(...input: unknown[]): void {
genericLogger(LogLevel.info, input)
},

warn(...input: any[]) {
warn(...input: unknown[]): void {
genericLogger(LogLevel.warn, input)
},

error(...input: any[]) {
error(...input: unknown[]): void {
genericLogger(LogLevel.error, input)
},
}
Expand Down
24 changes: 16 additions & 8 deletions background/lib/prices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ export async function getPrice(
return null
}

return json ? parseFloat(json[coingeckoCoinId][currencySymbol]) : null
return json
? parseFloat(
json[coingeckoCoinId][currencySymbol] as string // FIXME Drop as when strict mode arrives and price schema type can include this.
)
: null
}

function multiplyByFloat(n: bigint, f: number, precision: number) {
Expand Down Expand Up @@ -78,7 +82,7 @@ export async function getPrices(
amounts: [
multiplyByFloat(
BigInt(10) ** BigInt(c.decimals),
parseFloat(simpleCoinPrices[symbol]),
simpleCoinPrices[symbol] as number, // FIXME Drop as when strict mode arrives and price schema type can include this.
8
),
BigInt(1),
Expand Down Expand Up @@ -113,7 +117,14 @@ export async function getEthereumTokenPrices(
const prices: {
[index: string]: UnitPricePoint
} = {}
Object.entries(json).forEach(([address, priceDetails]) => {
// TODO Improve typing with Ajv validation.
Object.entries(
json as {
[address: string]: { last_updated_at: number } & {
[currencySymbol: string]: string
}
}
).forEach(([address, priceDetails]) => {
// TODO parse this as a fixed decimal rather than a number. Will require
// custom JSON deserialization
const price: number = Number.parseFloat(
Expand All @@ -128,12 +139,9 @@ export async function getEthereumTokenPrices(
symbol: currencySymbol.toUpperCase(),
decimals: fiatDecimals,
},
amount: BigInt(price * 10 ** fiatDecimals),
amount: BigInt(Math.trunc(price * 10 ** fiatDecimals)),
},
time: Number.parseInt(
(priceDetails as { last_updated_at }).last_updated_at || 0,
10
),
time: priceDetails.last_updated_at,
}
})
return prices
Expand Down
2 changes: 1 addition & 1 deletion background/lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export function normalizeEVMAddress(address: string | Buffer): HexString {
return normalizeHexAddress(address)
}

export function convertToEth(value: string | number): string {
export function convertToEth(value: string | number | bigint): string {
if (value && value >= 1) {
return utils.formatUnits(BigInt(value))
}
Expand Down
2 changes: 1 addition & 1 deletion background/lib/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const coingeckoPriceSchema = {
},
additionalProperties: true,
},
}
} as const

type CoinGeckoPriceDataJtd = JTDDataType<typeof coingeckoPriceSchema>

Expand Down
10 changes: 3 additions & 7 deletions background/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { browser } from "webextension-polyfill-ts"
import { alias, wrapStore } from "webext-redux"
import { configureStore, isPlain } from "@reduxjs/toolkit"
import { configureStore, isPlain, Middleware } from "@reduxjs/toolkit"
import devToolsEnhancer from "remote-redux-devtools"
import ethers from "ethers"

Expand Down Expand Up @@ -36,12 +36,8 @@ import { assetsLoaded, newPricePoint } from "./redux-slices/assets"
import {
emitter as keyringSliceEmitter,
updateKeyrings,
importLegacyKeyring,
} from "./redux-slices/keyrings"
import {
transactionOptions,
emitter as transactionSliceEmitter,
} from "./redux-slices/transaction"
import { emitter as transactionSliceEmitter } from "./redux-slices/transaction"
import { allAliases } from "./redux-slices/utils"
import BaseService from "./services/base"

Expand All @@ -63,7 +59,7 @@ const devToolsSanitizer = (input: unknown) => {
}
}

const reduxCache = (store) => (next) => (action) => {
const reduxCache: Middleware = (store) => (next) => (action) => {
const result = next(action)
const state = store.getState()

Expand Down
15 changes: 0 additions & 15 deletions background/migrations/index.ts

This file was deleted.

34 changes: 0 additions & 34 deletions background/migrations/v0.ts

This file was deleted.

Loading