Skip to content

Commit

Permalink
Merge branch 'main' into release-0.29.0
Browse files Browse the repository at this point in the history
  • Loading branch information
kkosiorowska authored Apr 5, 2023
2 parents b9cca73 + eb5e149 commit 9c3ace6
Show file tree
Hide file tree
Showing 36 changed files with 707 additions and 238 deletions.
21 changes: 19 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,26 @@ jobs:
cache: "yarn"
- run: yarn install --frozen-lockfile
- run: yarn lint
detect-if-flag-changed:
runs-on: ubuntu-latest
outputs:
path-filter: ${{ steps.filter.outputs.path-filter }}
steps:
- uses: actions/checkout@v3
if: github.event_name == 'pull_request'
- uses: dorny/paths-filter@v2
if: github.event_name == 'pull_request'
id: filter
with:
filters: |
path-filter:
- '.env.defaults'
e2e-tests:
if: (github.ref == 'refs/heads/main') || contains(github.head_ref, 'e2e')
needs: build
if: |
github.ref == 'refs/heads/main'
|| contains(github.head_ref, 'e2e')
|| needs.detect-if-flag-changed.outputs.path-filter == 'true'
needs: [build, detect-if-flag-changed]
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ well-organized GitHub issues for features and bugs, as well as organize folks
to tackle any issues they’re interested in. For the time being, the core team
will be charged with reviewing, critiquing, and ultimately merging new work.

⭐️ Check out our ["good first issues" tag](https://github.com/tahowallet/extension/issues?q=is%3Aopen+is%3Aissue+label%3A%22🐣+good+first+issue%22) for existing bugs that are more approachable.
⭐️ Check out our ["good first issues" tag](https://github.com/tahowallet/extension/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) for existing bugs that are more approachable.

## Use Feature Flags

When developing a new feature, please put it behind a feature flag. Because this enables you to open PRs in smaller chunks rather than having the feature completely finished, this will help your contributions get merged faster. It'll also help everyone better QA the feature and time its release! Feature flags are set in [`.env.defaults`](https://github.com/tahowallet/extension/blob/main/.env.defaults) in tandem with [`features.ts`](https://github.com/tahowallet/extension/blob/main/background/features.ts)

## Getting Started

1. Fork tahowallet/tally-extension
1. Fork tahowallet/extension
2. Clone your fork
3. Follow the [setup
instructions](https://github.com/tahowallet/tally-extension#building-and-developing).
instructions](https://github.com/tahowallet/extension#building-and-developing).
4. If you find an issue you would like to work on, post a comment indicating
you’d like to pick it up. Otherwise, please file an issue indicating what
you are intending to do—there could be a duplicate issue, or someone else
Expand Down
18 changes: 18 additions & 0 deletions background/lib/posthog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,25 @@ import logger from "./logger"
export enum AnalyticsEvent {
NEW_INSTALL = "New install",
UI_SHOWN = "UI shown",
ACCOUNT_NAME_EDITED = "Account Name Edited",
ANALYTICS_TOGGLED = "Analytics Toggled",
DEFAULT_WALLET_TOGGLED = "Default Wallet Toggled",
TRANSACTION_SIGNED = "Transaction Signed",
NEW_ACCOUNT_TO_TRACK = "Address added to tracking on network",
CUSTOM_CHAIN_ADDED = "Custom chain added",
DAPP_CONNECTED = "Dapp Connected",
}

export enum OneTimeAnalyticsEvent {
ONBOARDING_STARTED = "Onboarding Started",
ONBOARDING_FINISHED = "Onboarding Finished",
CHAIN_ADDED = "Chain Added",
}

export const isOneTimeAnalyticsEvent = (
eventName: string
): eventName is OneTimeAnalyticsEvent => {
return Object.values<string>(OneTimeAnalyticsEvent).includes(eventName)
}

const POSTHOG_PROJECT_ID = "11112"
Expand Down
124 changes: 118 additions & 6 deletions background/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {
} from "./services"

import { HexString, KeyringTypes, NormalizedEVMAddress } from "./types"
import { SignedTransaction } from "./networks"
import { EVMNetwork, SignedTransaction } from "./networks"
import { AccountBalance, AddressOnNetwork, NameOnNetwork } from "./accounts"
import { Eligible } from "./services/doggo/types"

Expand Down Expand Up @@ -75,6 +75,7 @@ import {
setAccountsSignerSettings,
toggleCollectAnalytics,
setShowAnalyticsNotification,
setSelectedNetwork,
} from "./redux-slices/ui"
import {
estimatedFeesPerGas,
Expand Down Expand Up @@ -167,7 +168,12 @@ import {
initAbilities,
} from "./redux-slices/abilities"
import { AddChainRequestData } from "./services/provider-bridge"
import { AnalyticsEvent } from "./lib/posthog"
import {
AnalyticsEvent,
isOneTimeAnalyticsEvent,
OneTimeAnalyticsEvent,
} from "./lib/posthog"
import { isBuiltInNetworkBaseAsset } from "./redux-slices/utils/asset-utils"

// This sanitizer runs on store and action data before serializing for remote
// redux devtools. The goal is to end up with an object that is directly
Expand Down Expand Up @@ -303,10 +309,7 @@ export default class Main extends BaseService<never> {
chainService
)

const analyticsService = AnalyticsService.create(
chainService,
preferenceService
)
const analyticsService = AnalyticsService.create(preferenceService)

const nftsService = NFTsService.create(chainService)

Expand Down Expand Up @@ -600,6 +603,7 @@ export default class Main extends BaseService<never> {
network,
name,
})
this.analyticsService.sendAnalyticsEvent(AnalyticsEvent.ACCOUNT_NAME_EDITED)
}

async removeAccount(
Expand Down Expand Up @@ -861,6 +865,12 @@ export default class Main extends BaseService<never> {
const signedTransactionResult =
await this.signingService.signTransaction(request, accountSigner)
await this.store.dispatch(transactionSigned(signedTransactionResult))
this.analyticsService.sendAnalyticsEvent(
AnalyticsEvent.TRANSACTION_SIGNED,
{
chainId: request.chainID,
}
)
} catch (exception) {
logger.error("Error signing transaction", exception)
this.store.dispatch(
Expand Down Expand Up @@ -986,6 +996,19 @@ export default class Main extends BaseService<never> {
sortedBalances.push(balance)
}

// Network base assets with smart contract addresses from some networks
// e.g. Optimism, Polygon might have been retrieved through alchemy as
// token balances but they should not be handled here as they would
// not be correctly treated as base assets
if (
isBuiltInNetworkBaseAsset(
balance.assetAmount.asset,
balance.network
)
) {
return false
}

return isSmartContract
})
// Sort trusted last to prevent shadowing assets from token lists
Expand Down Expand Up @@ -1325,6 +1348,12 @@ export default class Main extends BaseService<never> {
signingSliceEmitter.on("signatureRejected", rejectAndClear)
}
)
this.internalEthereumProviderService.emitter.on(
"selectedNetwork",
(network) => {
this.store.dispatch(setSelectedNetwork(network))
}
)

uiSliceEmitter.on("newSelectedNetwork", (network) => {
this.internalEthereumProviderService.routeSafeRPCRequest(
Expand Down Expand Up @@ -1393,6 +1422,10 @@ export default class Main extends BaseService<never> {
)

providerBridgeSliceEmitter.on("grantPermission", async (permission) => {
this.analyticsService.sendAnalyticsEvent(AnalyticsEvent.DAPP_CONNECTED, {
origin: permission.origin,
chainId: permission.chainID,
})
await Promise.all(
this.chainService.supportedNetworks.map(async (network) => {
await this.providerBridgeService.grantPermission({
Expand Down Expand Up @@ -1489,6 +1522,12 @@ export default class Main extends BaseService<never> {
this.providerBridgeService.notifyContentScriptAboutConfigChange(
newDefaultWalletValue
)
this.analyticsService.sendAnalyticsEvent(
AnalyticsEvent.DEFAULT_WALLET_TOGGLED,
{
setToDefault: newDefaultWalletValue,
}
)
}
)

Expand Down Expand Up @@ -1620,6 +1659,45 @@ export default class Main extends BaseService<never> {
this.store.dispatch(setShowAnalyticsNotification(true))
})

this.chainService.emitter.on("networkSubscribed", (network) => {
this.analyticsService.sendOneTimeAnalyticsEvent(
OneTimeAnalyticsEvent.CHAIN_ADDED,
{
chainId: network.chainID,
name: network.name,
description: `This event is fired when a chain is subscribed to from the wallet for the first time.`,
}
)
})

// ⚠️ Note: We NEVER send addresses to analytics!
this.chainService.emitter.on("newAccountToTrack", () => {
this.analyticsService.sendAnalyticsEvent(
AnalyticsEvent.NEW_ACCOUNT_TO_TRACK,
{
description: `
This event is fired when any address on a network is added to the tracked list.
Note: this does not track recovery phrase(ish) import! But when an address is used
on a network for the first time (read-only or recovery phrase/ledger/keyring).
`,
}
)
})

this.chainService.emitter.on("customChainAdded", (chainInfo) => {
this.analyticsService.sendAnalyticsEvent(
AnalyticsEvent.CUSTOM_CHAIN_ADDED,
{
description: `
This event is fired when a custom chain is added to the wallet.
`,
chainInfo: chainInfo.chainName,
chainId: chainInfo.chainId,
}
)
})

this.preferenceService.emitter.on(
"updateAnalyticsPreferences",
async (analyticsPreferences: AnalyticsPreferences) => {
Expand All @@ -1631,6 +1709,13 @@ export default class Main extends BaseService<never> {
analyticsPreferences.isEnabled
)
)

this.analyticsService.sendAnalyticsEvent(
AnalyticsEvent.ANALYTICS_TOGGLED,
{
analyticsEnabled: analyticsPreferences.isEnabled,
}
)
}
)

Expand All @@ -1646,6 +1731,14 @@ export default class Main extends BaseService<never> {
uiSliceEmitter.on("deleteAnalyticsData", () => {
this.analyticsService.removeAnalyticsData()
})

uiSliceEmitter.on("sendEvent", (event) => {
if (isOneTimeAnalyticsEvent(event)) {
this.analyticsService.sendOneTimeAnalyticsEvent(event)
} else {
this.analyticsService.sendAnalyticsEvent(event)
}
})
}

getAddNetworkRequestDetails(requestId: string): AddChainRequestData {
Expand Down Expand Up @@ -1707,17 +1800,36 @@ export default class Main extends BaseService<never> {
return this.chainService.removeCustomChain(chainID)
}

async importTokenViaContractAddress(
contractAddress: HexString,
network: EVMNetwork
): Promise<void> {
return this.indexingService.addTokenToTrackByContract(
network,
contractAddress
)
}

private connectPopupMonitor() {
runtime.onConnect.addListener((port) => {
if (port.name !== popupMonitorPortName) return

const openTime = Date.now()

const originalNetworkName =
this.store.getState().ui.selectedAccount.network.name

port.onDisconnect.addListener(() => {
const networkNameAtClose =
this.store.getState().ui.selectedAccount.network.name
this.analyticsService.sendAnalyticsEvent(AnalyticsEvent.UI_SHOWN, {
openTime: new Date(openTime).toISOString(),
closeTime: new Date().toISOString(),
openLength: (Date.now() - openTime) / 1e3,
networkName:
originalNetworkName === networkNameAtClose
? originalNetworkName
: "switched networks",
unit: "s",
})
this.onPopupDisconnected()
Expand Down
16 changes: 15 additions & 1 deletion background/redux-slices/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ import {
sameBuiltInNetworkBaseAsset,
} from "./utils/asset-utils"
import { getProvider } from "./utils/contract-utils"
import { sameNetwork } from "../networks"
import { EVMNetwork, sameNetwork } from "../networks"
import { ERC20_INTERFACE } from "../lib/erc20"
import logger from "../lib/logger"
import {
BUILT_IN_NETWORK_BASE_ASSETS,
FIAT_CURRENCIES_SYMBOL,
} from "../constants"
import { convertFixedPoint } from "../lib/fixed-point"
import { HexString } from "../types"

export type AssetWithRecentPrices<T extends AnyAsset = AnyAsset> = T & {
recentPrices: {
Expand Down Expand Up @@ -279,3 +280,16 @@ export const selectAssetPricePoint = createSelector(
return undefined
}
)

export const importTokenViaContractAddress = createBackgroundAsyncThunk(
"assets/importTokenViaContractAddress",
async (
{
contractAddress,
network,
}: { contractAddress: HexString; network: EVMNetwork },
{ extra: { main } }
) => {
await main.importTokenViaContractAddress(contractAddress, network)
}
)
Loading

0 comments on commit 9c3ace6

Please sign in to comment.