Skip to content

Commit

Permalink
Merge branch 'main' into trust-tokens-e2e
Browse files Browse the repository at this point in the history
  • Loading branch information
hyphenized authored Aug 16, 2023
2 parents 6bfbd18 + 169c8ed commit 0013d2a
Show file tree
Hide file tree
Showing 28 changed files with 291 additions and 639 deletions.
1 change: 0 additions & 1 deletion .env.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,3 @@ SUPPORT_SWAP_QUOTE_REFRESH=false
SUPPORT_ACHIEVEMENTS_BANNER=false
SUPPORT_NFT_SEND=false
USE_MAINNET_FORK=false
ENABLE_UPDATED_DAPP_CONNECTIONS=true
2 changes: 0 additions & 2 deletions background/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ export const RuntimeFlag = {
SUPPORT_SWAP_QUOTE_REFRESH: process.env.SUPPORT_SWAP_QUOTE_REFRESH === "true",
SUPPORT_CUSTOM_NETWORKS: process.env.SUPPORT_CUSTOM_NETWORKS === "true",
SUPPORT_CUSTOM_RPCS: process.env.SUPPORT_CUSTOM_RPCS === "true",
ENABLE_UPDATED_DAPP_CONNECTIONS:
process.env.ENABLE_UPDATED_DAPP_CONNECTIONS === "true",
} as const

type BuildTimeFlagType = keyof typeof BuildTimeFlag
Expand Down
63 changes: 55 additions & 8 deletions background/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ import {
REDUX_STATE_VERSION,
} from "./redux-slices/migrations"
import { PermissionMap } from "./services/provider-bridge/utils"
import { TALLY_INTERNAL_ORIGIN } from "./services/internal-ethereum-provider/constants"
import { TAHO_INTERNAL_ORIGIN } from "./services/internal-ethereum-provider/constants"
import {
ActivityDetail,
addActivity,
Expand Down Expand Up @@ -508,27 +508,74 @@ export default class Main extends BaseService<never> {
// Start up the redux store and set it up for proxying.
this.store = initializeStore(this, savedReduxState)

/**
* Tracks pending updates to the redux store. This is used to delay responding
* to dispatched thunks until the store has been updated in the UI. This is
* necessary to prevent race conditions where the UI expects the store to be
* updated before the thunk has finished dispatching.
*/
let storeUpdateLock: Promise<void> | null
let releaseLock: () => void

const queueUpdate = debounce(
(lastState, newState, updateFn) => {
if (lastState !== newState) {
const diff = deepDiff(lastState, newState)

if (diff !== undefined) {
updateFn(newState, [diff])
}
}
releaseLock()
},
30,
{ maxWait: 30, trailing: true }
)

wrapStore(this.store, {
serializer: encodeJSON,
deserializer: decodeJSON,
diffStrategy: (oldObj, newObj) => {
const diffWrapper = deepDiff(oldObj, newObj)
return diffWrapper === undefined ? [] : [diffWrapper]
diffStrategy: (oldObj, newObj, forceUpdate) => {
if (!storeUpdateLock) {
storeUpdateLock = new Promise((resolve) => {
releaseLock = () => {
resolve()
storeUpdateLock = null
}
})
}

queueUpdate(oldObj, newObj, forceUpdate)

// Return no diffs as we're manually handling these inside `queueUpdate`
return []
},
dispatchResponder: async (
dispatchResult: Promise<unknown>,
dispatchResult: Promise<unknown> | unknown,
send: (param: { error: string | null; value: unknown | null }) => void
) => {
try {
// if dispatch is a thunk, wait for the result
const result = await dispatchResult

// By this time, all pending updates should've been tracked.
// since we're dealing with a thunk, we need to wait for
// the store to be updated
await storeUpdateLock

send({
error: null,
value: encodeJSON(await dispatchResult),
value: encodeJSON(result),
})
} catch (error) {
logger.error(
"Error awaiting and dispatching redux store result: ",
error
)

// Store could still have been updated if there was an error
await storeUpdateLock

send({
error: encodeJSON(error),
value: null,
Expand Down Expand Up @@ -703,7 +750,7 @@ export default class Main extends BaseService<never> {
address: accounts[0].address,
network:
await this.internalEthereumProviderService.getCurrentOrDefaultNetworkForOrigin(
TALLY_INTERNAL_ORIGIN
TAHO_INTERNAL_ORIGIN
),
})
)
Expand Down Expand Up @@ -1363,7 +1410,7 @@ export default class Main extends BaseService<never> {
this.internalEthereumProviderService.routeSafeRPCRequest(
"wallet_switchEthereumChain",
[{ chainId: network.chainID }],
TALLY_INTERNAL_ORIGIN
TAHO_INTERNAL_ORIGIN
)
this.chainService.pollBlockPricesForNetwork(network.chainID)
this.store.dispatch(clearCustomGas())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// eslint-disable-next-line import/prefer-default-export
export const TALLY_INTERNAL_ORIGIN = "@tally-internal"
export const TAHO_INTERNAL_ORIGIN = "@tally-internal"
4 changes: 2 additions & 2 deletions background/services/internal-ethereum-provider/db.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Dexie from "dexie"
import { ETHEREUM } from "../../constants"
import { EVMNetwork } from "../../networks"
import { TALLY_INTERNAL_ORIGIN } from "./constants"
import { TAHO_INTERNAL_ORIGIN } from "./constants"

type NetworkForOrigin = {
origin: string
Expand Down Expand Up @@ -42,7 +42,7 @@ export class InternalEthereumProviderDatabase extends Dexie {
this.on("populate", (tx) =>
tx.db
.table("currentNetwork")
.add({ origin: TALLY_INTERNAL_ORIGIN, network: ETHEREUM })
.add({ origin: TAHO_INTERNAL_ORIGIN, network: ETHEREUM })
)
}

Expand Down
8 changes: 4 additions & 4 deletions background/services/internal-ethereum-provider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
parseSigningData,
} from "../../utils/signing"
import { getOrCreateDB, InternalEthereumProviderDatabase } from "./db"
import { TALLY_INTERNAL_ORIGIN } from "./constants"
import { TAHO_INTERNAL_ORIGIN } from "./constants"
import { ROOTSTOCK } from "../../constants"
import {
EnrichedEVMTransactionRequest,
Expand Down Expand Up @@ -145,7 +145,7 @@ export default class InternalEthereumProviderService extends BaseService<Events>
result: await this.routeSafeRPCRequest(
event.request.method,
event.request.params,
TALLY_INTERNAL_ORIGIN
TAHO_INTERNAL_ORIGIN
),
}
logger.debug("internal response:", response)
Expand Down Expand Up @@ -372,7 +372,7 @@ export default class InternalEthereumProviderService extends BaseService<Events>

private async getCurrentInternalNetwork(): Promise<EVMNetwork> {
return this.db.getCurrentNetworkForOrigin(
TALLY_INTERNAL_ORIGIN
TAHO_INTERNAL_ORIGIN
) as Promise<EVMNetwork>
}

Expand All @@ -398,7 +398,7 @@ export default class InternalEthereumProviderService extends BaseService<Events>
origin: string
): Promise<SignedTransaction> {
const annotation =
origin === TALLY_INTERNAL_ORIGIN &&
origin === TAHO_INTERNAL_ORIGIN &&
"annotation" in transactionRequest &&
transactionRequest.annotation !== undefined
? // We use `as` here as we know it's from a trusted source.
Expand Down
8 changes: 4 additions & 4 deletions background/services/provider-bridge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
EIP1193Error,
RPCRequest,
EIP1193_ERROR_CODES,
isTallyConfigPayload,
isTahoConfigPayload,
} from "@tallyho/provider-bridge-shared"
import { TransactionRequest as EthersTransactionRequest } from "@ethersproject/abstract-provider"
import BaseService from "../base"
Expand All @@ -35,7 +35,7 @@ import {
parseRPCRequestParams,
} from "./utils"
import { toHexChainID } from "../../networks"
import { TALLY_INTERNAL_ORIGIN } from "../internal-ethereum-provider/constants"
import { TAHO_INTERNAL_ORIGIN } from "../internal-ethereum-provider/constants"

type Events = ServiceLifecycleEvents & {
requestPermission: PermissionRequest
Expand Down Expand Up @@ -159,13 +159,13 @@ export default class ProviderBridgeService extends BaseService<Events> {
)

const originPermission = await this.checkPermission(origin, network.chainID)
if (origin === TALLY_INTERNAL_ORIGIN) {
if (origin === TAHO_INTERNAL_ORIGIN) {
// Explicitly disallow anyone who has managed to pretend to be the
// internal provider.
response.result = new EIP1193Error(
EIP1193_ERROR_CODES.unauthorized
).toJSON()
} else if (isTallyConfigPayload(event.request)) {
} else if (isTahoConfigPayload(event.request)) {
// let's start with the internal communication
response.id = "tallyHo"
response.result = {
Expand Down
65 changes: 65 additions & 0 deletions background/tests/differ.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import assert from "assert"
import { diff, patch } from "../differ"

describe("Diffing & Patching", () => {
describe("BigInts", () => {
const cases = [
0,
"test",
2n,
{ b: 1 },
[5],
null,
undefined,
true,
false,
"",
NaN,
]

test("Creates correct patches when diffing against bigints", () => {
cases.forEach((initial) => {
const expected = 9999n
const delta = diff(initial, expected)

assert(delta)
expect(patch(initial, delta)).toEqual(expected)
})
})

test("Creates correct patches when diffing from bigints", () => {
cases.forEach((expected) => {
const initial = 9999n
const delta = diff(initial, expected)

assert(delta)
expect(patch(initial, delta)).toEqual(expected)
})
})

test("Creates correct patches regardless of depth of change", () => {
cases.forEach((expected) => {
const targetFrom = { a: { b: [0, { c: 9999n }] } }
const target = { a: { b: [0, { c: expected }] } }

const delta = diff(targetFrom, target)

assert(delta)

expect(patch(targetFrom, delta)).toEqual(target)
})

// against bigints
cases.forEach((initial) => {
const targetFrom = { a: { b: [0, { c: initial }] } }
const target = { a: { b: [0, { c: 9999n }] } }

const delta = diff(targetFrom, target)

assert(delta)

expect(patch(targetFrom, delta)).toEqual(target)
})
})
})
})
1 change: 1 addition & 0 deletions e2e-tests/utils/onboarding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ export default class OnboardingHelper {
await page
.getByTestId("remaining_seed_words")
.getByRole("button", { name: word })
.first() // can be a duplicate word
.click()
}

Expand Down
10 changes: 9 additions & 1 deletion env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,29 @@ type WalletProvider = BaseWalletProvider & {

type TahoProvider = BaseWalletProvider & {
isTally: true
isTaho: true
tahoSetAsDefault: boolean
send: (method: string, params: unknown[]) => void | Promise<unknown>
}

type WindowEthereum = WalletProvider & {
isMetaMask?: boolean
tallySetAsDefault?: boolean
tahoSetAsDefault?: boolean
isTally?: boolean
isTaho?: boolean
autoRefreshOnNetworkChange?: boolean
}
interface Window {
walletRouter?: {
currentProvider: WalletProvider
providers: WalletProvider[]
shouldSetTallyForCurrentProvider: (
shouldSetTally: boolean,
shouldSetTaho: boolean,
shouldReload?: boolean
) => void
shouldSetTahoForCurrentProvider: (
shouldSetTaho: boolean,
shouldReload?: boolean
) => void
routeToNewNonTahoDefault: (request: unknown) => Promise<unknown>
Expand All @@ -68,6 +75,7 @@ interface Window {
addProvider: (newProvider: WalletProvider) => void
}
tally?: TahoProvider
taho?: TahoProvider
ethereum?: WindowEthereum
oldEthereum?: WindowEthereum
}
Expand Down
Loading

0 comments on commit 0013d2a

Please sign in to comment.