From d3d74e414ab6597f3c03fcf655ed19278c55b644 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Mon, 2 Oct 2023 22:52:58 -0400 Subject: [PATCH 01/17] Override Arbitrum mainnet when ARBITRUM_FORK_RPC is set Also set it by default to the Tenderly fork. --- .env.defaults | 1 + .../services/chain/serial-fallback-provider.ts | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/.env.defaults b/.env.defaults index d2914b14b..70f201130 100644 --- a/.env.defaults +++ b/.env.defaults @@ -31,3 +31,4 @@ SUPPORT_SWAP_QUOTE_REFRESH=false SUPPORT_ACHIEVEMENTS_BANNER=false SUPPORT_NFT_SEND=false USE_MAINNET_FORK=false +ARBITRUM_FORK_RPC=https://rpc.tenderly.co/fork/2fc2cf12-5c58-439f-9b5e-967bfd02191a diff --git a/background/services/chain/serial-fallback-provider.ts b/background/services/chain/serial-fallback-provider.ts index 9abc72ef8..07e5c11af 100644 --- a/background/services/chain/serial-fallback-provider.ts +++ b/background/services/chain/serial-fallback-provider.ts @@ -1090,6 +1090,19 @@ export function makeSerialFallbackProvider( ]) } + if ( + chainID === ARBITRUM_ONE.chainID && + process.env.ARBITRUM_FORK_RPC !== undefined && + process.env.ARBITRUM_FORK_RPC.trim() !== "" + ) { + return new SerialFallbackProvider(ARBITRUM_ONE.chainID, [ + { + type: "generic" as const, + creator: () => new JsonRpcBatchProvider(process.env.ARBITRUM_FORK_RPC), + }, + ]) + } + const alchemyProviderCreators: ProviderCreator[] = ALCHEMY_SUPPORTED_CHAIN_IDS.has(chainID) ? [ From 5aadbd441c718cd49906342cfe1e168a3e3aee39 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Tue, 3 Oct 2023 22:50:15 -0400 Subject: [PATCH 02/17] Add a skeleton for the portal Banner We use a dismissable item for the banner itself, which will be dismissed on clicking the Explore The Island link. No styling is included at the moment, and there is a stub for not displaying the banner unless the token has been detected as deployed---this part is not yet implemented. --- background/services/preferences/db.ts | 1 + ui/components/Wallet/Banner/PortalBanner.tsx | 35 ++++++++++++++++++++ ui/pages/Wallet.tsx | 2 ++ 3 files changed, 38 insertions(+) create mode 100644 ui/components/Wallet/Banner/PortalBanner.tsx diff --git a/background/services/preferences/db.ts b/background/services/preferences/db.ts index 4b902f0df..d0687ffa5 100644 --- a/background/services/preferences/db.ts +++ b/background/services/preferences/db.ts @@ -71,6 +71,7 @@ export type Preferences = { export type ManuallyDismissableItem = | "analytics-enabled-banner" | "copy-sensitive-material-warning" + | "testnet-portal-is-open-banner" /** * Items that the user will see once and will not be auto-displayed again. Can * be used for tours, or for popups that can be retriggered but will not diff --git a/ui/components/Wallet/Banner/PortalBanner.tsx b/ui/components/Wallet/Banner/PortalBanner.tsx new file mode 100644 index 000000000..71513b80e --- /dev/null +++ b/ui/components/Wallet/Banner/PortalBanner.tsx @@ -0,0 +1,35 @@ +import React, { ReactElement, useCallback } from "react" +import { + dismissableItemMarkedAsShown, + selectShouldShowDismissableItem, +} from "@tallyho/tally-background/redux-slices/ui" +import { useBackgroundDispatch, useBackgroundSelector } from "../../../hooks" + +export default function PortalBanner(): ReactElement | null { + const isTokenDeployed = true // useBackgroundSelector(isTestTahoDeployed) + const isBannerVisible = useBackgroundSelector( + selectShouldShowDismissableItem("testnet-portal-is-open-banner"), + ) + const dispatch = useBackgroundDispatch() + + const dismissBanner = () => + dispatch(dismissableItemMarkedAsShown("testnet-portal-is-open-banner")) + + if (!isTokenDeployed || !isBannerVisible) { + return null + } + + return ( +
+ The portal is open!{" "} + + Explore The Island + +
+ ) +} diff --git a/ui/pages/Wallet.tsx b/ui/pages/Wallet.tsx index a2a68d7d7..7bd726793 100644 --- a/ui/pages/Wallet.tsx +++ b/ui/pages/Wallet.tsx @@ -26,6 +26,7 @@ import NFTListCurrentWallet from "../components/NFTs/NFTListCurrentWallet" import WalletHiddenAssets from "../components/Wallet/WalletHiddenAssets" import SharedButton from "../components/Shared/SharedButton" import SharedIcon from "../components/Shared/SharedIcon" +import PortalBanner from "../components/Wallet/Banner/PortalBanner" export default function Wallet(): ReactElement { const { t } = useTranslation() @@ -113,6 +114,7 @@ export default function Wallet(): ReactElement { {!isEnabled(FeatureFlags.HIDE_TOKEN_FEATURES) && ( )} +
Date: Wed, 4 Oct 2023 16:04:03 -0400 Subject: [PATCH 03/17] Rename DoggoService to IslandService It will be used to handle the Island game on testnet. --- background/main.ts | 8 ++++---- background/services/index.ts | 2 +- background/services/{doggo => island}/contracts.ts | 0 background/services/{doggo => island}/db.ts | 0 background/services/{doggo => island}/defaults.ts | 0 background/services/{doggo => island}/index.ts | 0 background/services/{doggo => island}/types.ts | 0 background/services/{doggo => island}/utils.ts | 0 8 files changed, 5 insertions(+), 5 deletions(-) rename background/services/{doggo => island}/contracts.ts (100%) rename background/services/{doggo => island}/db.ts (100%) rename background/services/{doggo => island}/defaults.ts (100%) rename background/services/{doggo => island}/index.ts (100%) rename background/services/{doggo => island}/types.ts (100%) rename background/services/{doggo => island}/utils.ts (100%) diff --git a/background/main.ts b/background/main.ts index bdf071c31..6a35ec604 100644 --- a/background/main.ts +++ b/background/main.ts @@ -29,7 +29,7 @@ import { ProviderBridgeService, TelemetryService, ServiceCreatorFunction, - DoggoService, + IslandService, LedgerService, SigningService, NFTsService, @@ -41,7 +41,7 @@ import { import { HexString, NormalizedEVMAddress } from "./types" import { SignedTransaction } from "./networks" import { AccountBalance, AddressOnNetwork, NameOnNetwork } from "./accounts" -import { Eligible } from "./services/doggo/types" +import { Eligible } from "./services/island/types" import rootReducer from "./redux-slices" import { @@ -327,7 +327,7 @@ export default class Main extends BaseService { internalEthereumProviderService, preferenceService, ) - const doggoService = DoggoService.create(chainService, indexingService) + const doggoService = IslandService.create(chainService, indexingService) const telemetryService = TelemetryService.create() @@ -458,7 +458,7 @@ export default class Main extends BaseService { * A promise to the claim service, which saves the eligibility data * for efficient storage and retrieval. */ - private doggoService: DoggoService, + private doggoService: IslandService, /** * A promise to the telemetry service, which keeps track of extension * storage usage and (eventually) other statistics. diff --git a/background/services/index.ts b/background/services/index.ts index d3d709777..8572a1228 100644 --- a/background/services/index.ts +++ b/background/services/index.ts @@ -15,7 +15,7 @@ export { default as NameService } from "./name" export { default as PreferenceService } from "./preferences" export { default as ProviderBridgeService } from "./provider-bridge" export { default as InternalEthereumProviderService } from "./internal-ethereum-provider" -export { default as DoggoService } from "./doggo" +export { default as IslandService } from "./island" export { default as TelemetryService } from "./telemetry" export { default as LedgerService } from "./ledger" export { default as SigningService } from "./signing" diff --git a/background/services/doggo/contracts.ts b/background/services/island/contracts.ts similarity index 100% rename from background/services/doggo/contracts.ts rename to background/services/island/contracts.ts diff --git a/background/services/doggo/db.ts b/background/services/island/db.ts similarity index 100% rename from background/services/doggo/db.ts rename to background/services/island/db.ts diff --git a/background/services/doggo/defaults.ts b/background/services/island/defaults.ts similarity index 100% rename from background/services/doggo/defaults.ts rename to background/services/island/defaults.ts diff --git a/background/services/doggo/index.ts b/background/services/island/index.ts similarity index 100% rename from background/services/doggo/index.ts rename to background/services/island/index.ts diff --git a/background/services/doggo/types.ts b/background/services/island/types.ts similarity index 100% rename from background/services/doggo/types.ts rename to background/services/island/types.ts diff --git a/background/services/doggo/utils.ts b/background/services/island/utils.ts similarity index 100% rename from background/services/doggo/utils.ts rename to background/services/island/utils.ts From 70408839cfa79a57b35c1cde45dc828eeaff9150 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Wed, 4 Oct 2023 16:04:31 -0400 Subject: [PATCH 04/17] Add `isTrackingAsset` to indexing service This was already available on the db, but unexposed. --- background/services/indexing/index.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/background/services/indexing/index.ts b/background/services/indexing/index.ts index af09e63fc..d033f3ae1 100644 --- a/background/services/indexing/index.ts +++ b/background/services/indexing/index.ts @@ -242,6 +242,15 @@ export default class IndexingService extends BaseService { await this.db.addAssetToTrack(asset) } + /** + * Check whether the specified asset is already being tracked. + * + * @param asset The fungible asset to track. + */ + async isTrackingAsset(asset: SmartContractFungibleAsset): Promise { + return this.db.isTrackingAsset(asset) + } + /** * Adds/updates a custom asset, invalidates internal cache for asset network * @param asset The custom asset From a512089d89b7b33b77bfa04b6646dbfc7d82a2ce Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Wed, 4 Oct 2023 16:05:28 -0400 Subject: [PATCH 05/17] Add SUPPORT_THE_ISLAND_TESTNET feature flag and related env variables The two env variables we add for now are for the Taho deployer and TAHO itself on testnet. We can derive the TAHO address from the deployer, but for now it will live in a constant and thus must be specified ahead of time. --- .env.defaults | 3 +++ background/features.ts | 1 + 2 files changed, 4 insertions(+) diff --git a/.env.defaults b/.env.defaults index 70f201130..197077886 100644 --- a/.env.defaults +++ b/.env.defaults @@ -30,5 +30,8 @@ SUPPORT_ARBITRUM_NOVA=false SUPPORT_SWAP_QUOTE_REFRESH=false SUPPORT_ACHIEVEMENTS_BANNER=false SUPPORT_NFT_SEND=false +SUPPORT_THE_ISLAND_TESTNET=false USE_MAINNET_FORK=false ARBITRUM_FORK_RPC=https://rpc.tenderly.co/fork/2fc2cf12-5c58-439f-9b5e-967bfd02191a +TESTNET_TAHO_DEPLOYER_ADDRESS=0x267919C3757561672C5499882D7F64DfeA78D067 +TESTNET_TAHO_ADDRESS=0x267919C3757561672C5499882D7F64DfeA78D067 diff --git a/background/features.ts b/background/features.ts index ecf56afa9..e4258f352 100644 --- a/background/features.ts +++ b/background/features.ts @@ -23,6 +23,7 @@ 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", + SUPPORT_THE_ISLAND_TESTNET: process.env.SUPPORT_THE_ISLAND_TESTNET === "true", } as const type BuildTimeFlagType = keyof typeof BuildTimeFlag From 18a209186699e26634b5ae0dfe1a0fef0ccc9e8d Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Wed, 4 Oct 2023 16:07:14 -0400 Subject: [PATCH 06/17] Add monitoring for island assets on testnet These are, currently, the TAHO token as well as the realm XP tokens for each of the starting realms. Starting realms are named due to the way the deployer works, and those names are hardcoded for the testnet. Eventually we'll want to iterate these from the game contract. --- background/services/island/contracts.ts | 2077 +++++++++++++++++++++++ background/services/island/db.ts | 8 +- background/services/island/index.ts | 94 +- 3 files changed, 2157 insertions(+), 22 deletions(-) diff --git a/background/services/island/contracts.ts b/background/services/island/contracts.ts index b33b966fe..cc40c98c4 100644 --- a/background/services/island/contracts.ts +++ b/background/services/island/contracts.ts @@ -1,5 +1,2062 @@ import { ethers } from "ethers" import { VOTE_WITH_FRIENDS_ADDRESS } from "../../redux-slices/claim" +import { SmartContractFungibleAsset } from "../../assets" +import { WEBSITE_ORIGIN } from "../../constants/website" +import { ARBITRUM_ONE } from "../../constants" +import {HexString, NormalizedEVMAddress} from "../../types" + +export const TESTNET_TAHO: SmartContractFungibleAsset = { + name: "Taho", + symbol: "TAHO", + decimals: 18, + contractAddress: + process.env.TESTNET_TAHO_ADDRESS ?? ethers.constants.AddressZero, + homeNetwork: ARBITRUM_ONE, + metadata: { + tokenLists: [], + websiteURL: WEBSITE_ORIGIN, + }, +} + +export const TESTNET_TAHO_DEPLOYER_ADDRESS = + process.env.TESTNET_TAHO_DEPLOYER_ADDRESS ?? ethers.constants.AddressZero + +const TESTNET_XP_ABI = [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint256", + "name": "season_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "season", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + +const TESTNET_REALM_ABI = [ + { + inputs: [ + { + internalType: "string", + name: "realmName", + type: "string", + }, + { + internalType: "string", + name: "_xpTokenNamePrefix", + type: "string", + }, + { + internalType: "string", + name: "_xpTokenSymbolPrefix", + type: "string", + }, + { + internalType: "contract GameParameters", + name: "_gameParameters", + type: "address", + }, + { + internalType: "contract Game", + name: "_game", + type: "address", + }, + { + internalType: "contract Taho", + name: "_taho", + type: "address", + }, + { + internalType: "contract VeTaho", + name: "_veTaho", + type: "address", + }, + { + internalType: "address", + name: "initialCouncil", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [ + { + internalType: "uint256", + name: "actual", + type: "uint256", + }, + { + internalType: "uint256", + name: "required", + type: "uint256", + }, + ], + name: "NotEnoughSignatures", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "oldCouncilAddress", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newCouncilAddress", + type: "address", + }, + ], + name: "CouncilAddressUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address[]", + name: "oldMembers", + type: "address[]", + }, + { + indexed: false, + internalType: "address[]", + name: "newMembers", + type: "address[]", + }, + ], + name: "CouncilMembersUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "newName", + type: "string", + }, + ], + name: "NameUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "newQuestlineUrl", + type: "string", + }, + ], + name: "QuestlineUrlUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "staker", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "unlockAt", + type: "uint256", + }, + ], + name: "Staked", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "staker", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Unstaked", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "newVersion", + type: "address", + }, + ], + name: "UpgradeFinalized", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "newVersion", + type: "address", + }, + ], + name: "UpgradeInitiated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "season", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "xp", + type: "address", + }, + ], + name: "XpCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "xp", + type: "address", + }, + { + indexed: false, + internalType: "string", + name: "merkleDataUrl", + type: "string", + }, + { + indexed: false, + internalType: "bytes32", + name: "merkleRoot", + type: "bytes32", + }, + { + indexed: false, + internalType: "address", + name: "distributor", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "XpDistributed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "bytes32", + name: "newXpFunctionHash", + type: "bytes32", + }, + ], + name: "XpFunctionUpdated", + type: "event", + }, + { + inputs: [], + name: "DOMAIN_SEPARATOR", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "UPDATE_COUNCIL_TYPEHASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "cachedChainId", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "cachedDomainSeparator", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "newXpFunctionHash", + type: "bytes32", + }, + ], + name: "commitXpFunction", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "council", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + name: "councilMembers", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "createXp", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "merkleRoot", + type: "bytes32", + }, + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + { + internalType: "string", + name: "merkleDataUrl", + type: "string", + }, + ], + name: "distributeXp", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "finalizeUpgrade", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "game", + outputs: [ + { + internalType: "contract Game", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "gameParameters", + outputs: [ + { + internalType: "contract GameParameters", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getCouncilMembers", + outputs: [ + { + internalType: "address[]", + name: "", + type: "address[]", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_newVersion", + type: "address", + }, + ], + name: "initiateUpgrade", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "newVersion", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + name: "nonces", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "questlineUrl", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "typeHashDigest", + type: "bytes32", + }, + { + internalType: "uint8", + name: "v", + type: "uint8", + }, + { + internalType: "bytes32", + name: "r", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "s", + type: "bytes32", + }, + ], + name: "recoverFromTypeHashSignature", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address[]", + name: "newCouncilMembers", + type: "address[]", + }, + ], + name: "setCouncilMembers", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "stake", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + name: "stakeUnlockTime", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "taho", + outputs: [ + { + internalType: "contract Taho", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "unstake", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newCouncil", + type: "address", + }, + { + internalType: "bytes", + name: "signatures", + type: "bytes", + }, + ], + name: "updateCouncilAddress", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "string", + name: "newName", + type: "string", + }, + ], + name: "updateName", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "string", + name: "newQuestlineUrl", + type: "string", + }, + ], + name: "updateQuestlineUrl", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "veTaho", + outputs: [ + { + internalType: "contract VeTaho", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "xp", + outputs: [ + { + internalType: "contract Xp", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "xpFunctionHash", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "xpTokenNamePrefix", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "xpTokenSymbolPrefix", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, +] + +const TESTNET_TAHO_DEPLOYER_ABI = [ + { + inputs: [], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "deployHash", + type: "bytes32", + }, + ], + name: "UnknownContract", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "contractAddress", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "deployerAddress", + type: "address", + }, + ], + name: "Deployed", + type: "event", + }, + { + inputs: [], + name: "APPROVAL_TARGET", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "APPROVAL_TARGET_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "BALANCER_POOL", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "BALANCER_POOL_AGENT", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "BALANCER_POOL_AGENT_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "BALANCER_POOL_CANDIDATE", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "BALANCER_POOL_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "CLAIM_WITH_FRIENDS", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "CLAIM_WITH_FRIENDS_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "CREATORS_REALM", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "CREATORS_REALM_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "CREATORS_REALM_VETAHO", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "CREATORS_REALM_VETAHO_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DEFI_REALM", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DEFI_REALM_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DEFI_REALM_VETAHO", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DEFI_REALM_VETAHO_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DEV_GRANT_ESCROW", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DEV_GRANT_ESCROW_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DEV_TEAM_MULTISIG", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "EDUCATE_REALM", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "EDUCATE_REALM_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "EDUCATE_REALM_VETAHO", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "EDUCATE_REALM_VETAHO_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "ELECTIONS", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "ELECTIONS_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "EXPIRING_MERKLE_DISTRIBUTOR_FACTORY", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "GAME", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "GAME_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "GAME_PARAMETERS", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "GAME_PARAMETERS_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "HUNTING_GROUND_REGISTRY", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "HUNTING_GROUND_REGISTRY_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "HUNTING_GROUND_REWARDS_ESCROW", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "HUNTING_GROUND_REWARDS_ESCROW_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "MERKLE_FACTORY_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "SOCIAL_REALM", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "SOCIAL_REALM_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "SOCIAL_REALM_VETAHO", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "SOCIAL_REALM_VETAHO_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "TAHO_COMMUNITY_MULTISIG", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "TAHO_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "TAHO_ETH_HUNTING_GROUND", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "TAHO_ETH_HUNTING_GROUND_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "TAHO_SALT", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "TAHO_TOKEN", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "TREASURY_VESTER", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "TREASURY_VESTER_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "VAMPIRE_REALM", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "VAMPIRE_REALM_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "VAMPIRE_REALM_VETAHO", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "VAMPIRE_REALM_VETAHO_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "XP", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "XP_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "XP_FACTORY", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "XP_FACTORY_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "XP_MERKLE_DISTRIBUTOR_FACTORY", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "XP_MERKLE_DISTRIBUTOR_FACTORY_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "XP_TAHO_CONVERTER_FACTORY", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "XP_TAHO_CONVERTER_FACTORY_DEPLOYER_DEPLOY_HASH", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + name: "contractRewards", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "contractsPendingDeploymentCount", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes", + name: "_initCode", + type: "bytes", + }, + ], + name: "deploy", + outputs: [ + { + internalType: "address payable", + name: "createdContract", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "finalize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "balancerPoolCandidate", + type: "address", + }, + ], + name: "setBalancerPoolCandidate", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const export const CLAIM_WITH_FRIENDS_ABI = [ { @@ -276,7 +2333,27 @@ export const CLAIM_WITH_FRIENDS_ABI = [ }, ] as const +export const STARTING_REALM_NAMES = [ + "Creators", + "Defi", + "Educate", + "Social", + "Vampire", +] + +export function buildRealmContract(address: NormalizedEVMAddress): ethers.Contract { + return new ethers.Contract( + address, + TESTNET_REALM_ABI + ) +} + export const ClaimWithFriends = new ethers.Contract( VOTE_WITH_FRIENDS_ADDRESS, // "** address from calling DoggoDeployer.VOTE_WITH_FRIENDS(), this should probably be a function **", CLAIM_WITH_FRIENDS_ABI, ) + +export const TestnetTahoDeployer = new ethers.Contract( + TESTNET_TAHO_DEPLOYER_ADDRESS, + TESTNET_TAHO_DEPLOYER_ABI, +) diff --git a/background/services/island/db.ts b/background/services/island/db.ts index c10310183..2f0573e33 100644 --- a/background/services/island/db.ts +++ b/background/services/island/db.ts @@ -7,14 +7,14 @@ export type ReferrerStats = { referredUsers: number } -export class DoggoDatabase extends Dexie { +export class IslandDatabase extends Dexie { private referralBonuses!: Dexie.Table< AddressOnNetwork & { referredBy: AddressOnNetwork; referralBonus: bigint }, [string, string, string] > constructor() { - super("tally/doggo") + super("taho/island") this.version(1).stores({ referralBonuses: @@ -54,6 +54,6 @@ export class DoggoDatabase extends Dexie { } } -export async function getOrCreateDB(): Promise { - return new DoggoDatabase() +export async function getOrCreateDB(): Promise { + return new IslandDatabase() } diff --git a/background/services/island/index.ts b/background/services/island/index.ts index 233d7b03d..283f25ddc 100644 --- a/background/services/island/index.ts +++ b/background/services/island/index.ts @@ -4,17 +4,25 @@ import { Eligible } from "./types" import BaseService from "../base" import { getFileHashProspect, getClaimFromFileHash } from "./utils" import ChainService from "../chain" -import { DOGGO, ETHEREUM } from "../../constants" +import { ARBITRUM_ONE, DOGGO, ETHEREUM } from "../../constants" import { sameNetwork } from "../../networks" -import { ClaimWithFriends } from "./contracts" +import { + ClaimWithFriends, + STARTING_REALM_NAMES, + TESTNET_TAHO, + TestnetTahoDeployer, + buildRealmContract, +} from "./contracts" import IndexingService from "../indexing" import { initialVaults } from "../../redux-slices/earn" import logger from "../../lib/logger" import { HexString } from "../../types" import { AddressOnNetwork } from "../../accounts" -import { DoggoDatabase, getOrCreateDB, ReferrerStats } from "./db" +import { IslandDatabase, getOrCreateDB, ReferrerStats } from "./db" import { normalizeEVMAddress } from "../../lib/utils" -import { FeatureFlags, isEnabled } from "../../features" +import { FeatureFlags, isDisabled, isEnabled } from "../../features" + +export { TESTNET_TAHO, TestnetTahoDeployer as TahoDeployer } from "./contracts" interface Events extends ServiceLifecycleEvents { newEligibility: Eligible @@ -22,39 +30,89 @@ interface Events extends ServiceLifecycleEvents { } /* - * The DOGGO service handles interactions, caching, and indexing related to the - * DOGGO token and its capabilities. + * The Island service handles interactions, caching, and indexing related to + * the Island game and its capabilities. * - * This includes handling DOGGO claim data, as well as + * This includes handling Island contracts, as well as metadata that is best + * maintained in-wallet around XP, etc. */ -export default class DoggoService extends BaseService { +export default class IslandService extends BaseService { + private isRelevantMonitoringEnabled = false + static create: ServiceCreatorFunction< Events, - DoggoService, + IslandService, [Promise, Promise] > = async (chainService, indexingService) => new this(await getOrCreateDB(), await chainService, await indexingService) private constructor( - private db: DoggoDatabase, + private db: IslandDatabase, private chainService: ChainService, private indexingService: IndexingService, ) { - super() + super({ + startMonitoringIfNeeded: { + schedule: { + periodInMinutes: 10, + }, + handler: () => this.startMonitoringIfNeeded, + runAtStart: true, + }, + }) } - protected override async internalStartService(): Promise { - await super.internalStartService() + private async startMonitoringIfNeeded(): Promise { + if (isDisabled(FeatureFlags.SUPPORT_THE_ISLAND_TESTNET)) { + this.isRelevantMonitoringEnabled = true + return + } - const huntingGrounds = initialVaults + if (this.isRelevantMonitoringEnabled) { + return + } - const ethereumProvider = this.chainService.providerForNetwork(ETHEREUM) - if (ethereumProvider === undefined) { - logger.error( - "No Ethereum provider available, not setting up DOGGO monitoring...", + const arbitrumProvider = this.chainService.providerForNetwork(ARBITRUM_ONE) + if (arbitrumProvider === undefined) { + logger.debug( + "No Arbitrum provider available, not setting up The Island...", ) + + return + } + + if (!this.indexingService.isTrackingAsset(TESTNET_TAHO)) { + this.indexingService.addAssetToTrack(TESTNET_TAHO) } + const connectedDeployer = TestnetTahoDeployer.connect(arbitrumProvider) + await Promise.all( + STARTING_REALM_NAMES.map(async (realmName) => { + const realmAddress = + await connectedDeployer.functions[ + `${realmName.toUpperCase()}_REALM` + ]() + const realmContract = + buildRealmContract(realmAddress).connect(arbitrumProvider) + + const xpAddress = await realmContract.functions.xp() + await this.indexingService.addTokenToTrackByContract( + ARBITRUM_ONE, + xpAddress, + { verified: true }, + ) + }), + ) + + // If all monitoring is enabled successfully, don't try again later. + this.isRelevantMonitoringEnabled = true + } + + protected override async internalStartService(): Promise { + await super.internalStartService() + + const huntingGrounds = initialVaults + if (!isEnabled(FeatureFlags.HIDE_TOKEN_FEATURES)) { // Make sure the hunting ground assets are being tracked. huntingGrounds.forEach(({ network, asset }) => { From 5d1f0f0ad8d32248aa83c5adfa73992934e900bc Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Wed, 4 Oct 2023 16:31:04 -0400 Subject: [PATCH 07/17] Further island renames and related rearrangements References in main and the claim slice weren't fully updated, and fixing those references required rearranging where certain constants were to avoid circular dependencies. The island network has also been abstracted to a constant based on whether the Arbitrum fork is defined or not. --- background/main.ts | 22 +- background/redux-slices/claim.ts | 10 +- background/services/island/contracts.ts | 433 +----------------------- background/services/island/db.ts | 6 +- background/services/island/index.ts | 30 +- 5 files changed, 52 insertions(+), 449 deletions(-) diff --git a/background/main.ts b/background/main.ts index 6a35ec604..2b3858796 100644 --- a/background/main.ts +++ b/background/main.ts @@ -327,7 +327,7 @@ export default class Main extends BaseService { internalEthereumProviderService, preferenceService, ) - const doggoService = IslandService.create(chainService, indexingService) + const islandService = IslandService.create(chainService, indexingService) const telemetryService = TelemetryService.create() @@ -399,7 +399,7 @@ export default class Main extends BaseService { await nameService, await internalEthereumProviderService, await providerBridgeService, - await doggoService, + await islandService, await telemetryService, await ledgerService, await signingService, @@ -458,7 +458,7 @@ export default class Main extends BaseService { * A promise to the claim service, which saves the eligibility data * for efficient storage and retrieval. */ - private doggoService: IslandService, + private islandService: IslandService, /** * A promise to the telemetry service, which keeps track of extension * storage usage and (eventually) other statistics. @@ -602,7 +602,7 @@ export default class Main extends BaseService { this.nameService.startService(), this.internalEthereumProviderService.startService(), this.providerBridgeService.startService(), - this.doggoService.startService(), + this.islandService.startService(), this.telemetryService.startService(), this.ledgerService.startService(), this.signingService.startService(), @@ -625,7 +625,7 @@ export default class Main extends BaseService { this.nameService.stopService(), this.internalEthereumProviderService.stopService(), this.providerBridgeService.stopService(), - this.doggoService.stopService(), + this.islandService.stopService(), this.telemetryService.stopService(), this.ledgerService.stopService(), this.signingService.stopService(), @@ -647,7 +647,7 @@ export default class Main extends BaseService { this.connectProviderBridgeService() this.connectPreferenceService() this.connectEnrichmentService() - this.connectDoggoService() + this.connectIslandService() this.connectTelemetryService() this.connectLedgerService() this.connectSigningService() @@ -1584,14 +1584,14 @@ export default class Main extends BaseService { this.store.dispatch(clearSwapQuote()) this.store.dispatch(setEligibilityLoading()) - this.doggoService.getEligibility(addressNetwork.address) + this.islandService.getEligibility(addressNetwork.address) this.store.dispatch(setVaultsAsStale()) await this.chainService.markAccountActivity(addressNetwork) const referrerStats = - await this.doggoService.getReferrerStats(addressNetwork) + await this.islandService.getReferrerStats(addressNetwork) this.store.dispatch(setReferrerStats(referrerStats)) this.providerBridgeService.notifyContentScriptsAboutAddressChange( @@ -1629,15 +1629,15 @@ export default class Main extends BaseService { }) } - async connectDoggoService(): Promise { - this.doggoService.emitter.on( + async connectIslandService(): Promise { + this.islandService.emitter.on( "newEligibility", async (eligibility: Eligible) => { await this.store.dispatch(setEligibility(eligibility)) }, ) - this.doggoService.emitter.on( + this.islandService.emitter.on( "newReferral", async ( referral: { diff --git a/background/redux-slices/claim.ts b/background/redux-slices/claim.ts index f40a2a891..9240362cc 100644 --- a/background/redux-slices/claim.ts +++ b/background/redux-slices/claim.ts @@ -1,7 +1,7 @@ import { createSlice, createSelector } from "@reduxjs/toolkit" import { BigNumber, Signature, utils } from "ethers" import { TransactionResponse } from "@ethersproject/abstract-provider" -import { Eligible } from "../services/doggo/types" +import { Eligible } from "../services/island/types" import { createBackgroundAsyncThunk } from "./utils" import { normalizeEVMAddress, truncateAddress } from "../lib/utils" @@ -19,7 +19,11 @@ import DISTRIBUTOR_ABI from "./contract-abis/merkle-distributor" import { DOGGO, HOUR } from "../constants" import { FeatureFlags, isEnabled } from "../features" import { ERC2612_INTERFACE } from "../lib/erc20" -import { ReferrerStats } from "../services/doggo/db" +import { + ReferrerStats, + TESTNET_TAHO, + VOTE_WITH_FRIENDS_ADDRESS, +} from "../services/island" import { fromFixedPointNumber } from "../lib/fixed-point" export interface DAO { @@ -64,8 +68,6 @@ interface ClaimingState { } const DOGGO_TOKEN_ADDRESS = DOGGO.contractAddress -export const VOTE_WITH_FRIENDS_ADDRESS = - "0x0036B3a9D385Ce2CC072cf4A26dE29aE3283DEd0" const getDistributorContract = async () => { const distributorContractAddress = VOTE_WITH_FRIENDS_ADDRESS // VoteWithFriends contract address diff --git a/background/services/island/contracts.ts b/background/services/island/contracts.ts index cc40c98c4..ef810e254 100644 --- a/background/services/island/contracts.ts +++ b/background/services/island/contracts.ts @@ -1,9 +1,17 @@ import { ethers } from "ethers" -import { VOTE_WITH_FRIENDS_ADDRESS } from "../../redux-slices/claim" import { SmartContractFungibleAsset } from "../../assets" import { WEBSITE_ORIGIN } from "../../constants/website" -import { ARBITRUM_ONE } from "../../constants" -import {HexString, NormalizedEVMAddress} from "../../types" +import { ARBITRUM_ONE, ARBITRUM_SEPOLIA } from "../../constants" +import { NormalizedEVMAddress } from "../../types" + +export const ISLAND_NETWORK = + process.env.ARBITRUM_FORK_RPC === undefined || + process.env.ARBITRUM_FORK_RPC.trim() === "" + ? ARBITRUM_SEPOLIA + : ARBITRUM_ONE + +export const VOTE_WITH_FRIENDS_ADDRESS = + "0x0036B3a9D385Ce2CC072cf4A26dE29aE3283DEd0" export const TESTNET_TAHO: SmartContractFungibleAsset = { name: "Taho", @@ -21,416 +29,6 @@ export const TESTNET_TAHO: SmartContractFungibleAsset = { export const TESTNET_TAHO_DEPLOYER_ADDRESS = process.env.TESTNET_TAHO_DEPLOYER_ADDRESS ?? ethers.constants.AddressZero -const TESTNET_XP_ABI = [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "name_", - "type": "string" - }, - { - "internalType": "string", - "name": "symbol_", - "type": "string" - }, - { - "internalType": "uint256", - "name": "season_", - "type": "uint256" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "season", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] - const TESTNET_REALM_ABI = [ { inputs: [ @@ -2341,11 +1939,10 @@ export const STARTING_REALM_NAMES = [ "Vampire", ] -export function buildRealmContract(address: NormalizedEVMAddress): ethers.Contract { - return new ethers.Contract( - address, - TESTNET_REALM_ABI - ) +export function buildRealmContract( + address: NormalizedEVMAddress, +): ethers.Contract { + return new ethers.Contract(address, TESTNET_REALM_ABI) } export const ClaimWithFriends = new ethers.Contract( diff --git a/background/services/island/db.ts b/background/services/island/db.ts index 2f0573e33..e9b41af1b 100644 --- a/background/services/island/db.ts +++ b/background/services/island/db.ts @@ -1,11 +1,7 @@ import Dexie from "dexie" import { AddressOnNetwork } from "../../accounts" import { normalizeEVMAddress } from "../../lib/utils" - -export type ReferrerStats = { - bonusTotal: bigint - referredUsers: number -} +import { ReferrerStats } from "./types" export class IslandDatabase extends Dexie { private referralBonuses!: Dexie.Table< diff --git a/background/services/island/index.ts b/background/services/island/index.ts index 283f25ddc..4b7ac0256 100644 --- a/background/services/island/index.ts +++ b/background/services/island/index.ts @@ -1,13 +1,14 @@ import { BigNumber } from "ethers" import { ServiceLifecycleEvents, ServiceCreatorFunction } from "../types" -import { Eligible } from "./types" +import { Eligible, ReferrerStats } from "./types" import BaseService from "../base" import { getFileHashProspect, getClaimFromFileHash } from "./utils" import ChainService from "../chain" -import { ARBITRUM_ONE, DOGGO, ETHEREUM } from "../../constants" +import { DOGGO, ETHEREUM } from "../../constants" import { sameNetwork } from "../../networks" import { ClaimWithFriends, + ISLAND_NETWORK, STARTING_REALM_NAMES, TESTNET_TAHO, TestnetTahoDeployer, @@ -18,11 +19,18 @@ import { initialVaults } from "../../redux-slices/earn" import logger from "../../lib/logger" import { HexString } from "../../types" import { AddressOnNetwork } from "../../accounts" -import { IslandDatabase, getOrCreateDB, ReferrerStats } from "./db" +import { IslandDatabase, getOrCreateDB } from "./db" import { normalizeEVMAddress } from "../../lib/utils" import { FeatureFlags, isDisabled, isEnabled } from "../../features" +import { SmartContractFungibleAsset } from "../../assets" -export { TESTNET_TAHO, TestnetTahoDeployer as TahoDeployer } from "./contracts" +export { + TESTNET_TAHO, + VOTE_WITH_FRIENDS_ADDRESS, + TestnetTahoDeployer as TahoDeployer, +} from "./contracts" + +export { ReferrerStats } from "./types" interface Events extends ServiceLifecycleEvents { newEligibility: Eligible @@ -72,8 +80,8 @@ export default class IslandService extends BaseService { return } - const arbitrumProvider = this.chainService.providerForNetwork(ARBITRUM_ONE) - if (arbitrumProvider === undefined) { + const islandProvider = this.chainService.providerForNetwork(ISLAND_NETWORK) + if (islandProvider === undefined) { logger.debug( "No Arbitrum provider available, not setting up The Island...", ) @@ -82,10 +90,10 @@ export default class IslandService extends BaseService { } if (!this.indexingService.isTrackingAsset(TESTNET_TAHO)) { - this.indexingService.addAssetToTrack(TESTNET_TAHO) + await this.indexingService.addAssetToTrack(TESTNET_TAHO) } - const connectedDeployer = TestnetTahoDeployer.connect(arbitrumProvider) + const connectedDeployer = TestnetTahoDeployer.connect(islandProvider) await Promise.all( STARTING_REALM_NAMES.map(async (realmName) => { const realmAddress = @@ -93,11 +101,11 @@ export default class IslandService extends BaseService { `${realmName.toUpperCase()}_REALM` ]() const realmContract = - buildRealmContract(realmAddress).connect(arbitrumProvider) + buildRealmContract(realmAddress).connect(islandProvider) const xpAddress = await realmContract.functions.xp() - await this.indexingService.addTokenToTrackByContract( - ARBITRUM_ONE, + const asset = await this.indexingService.addTokenToTrackByContract( + ISLAND_NETWORK, xpAddress, { verified: true }, ) From 7f14477c4ae00a4d5f419d81b9a5137b77682f6d Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Wed, 4 Oct 2023 16:31:40 -0400 Subject: [PATCH 08/17] Track monitored Island assets in claim slice --- background/main.ts | 2 ++ background/redux-slices/claim.ts | 10 ++++++++++ background/services/island/index.ts | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/background/main.ts b/background/main.ts index 2b3858796..adc33b2c2 100644 --- a/background/main.ts +++ b/background/main.ts @@ -1660,6 +1660,8 @@ export default class Main extends BaseService { } }, ) + + this.islandService.emitter.on("monitoringTestnetAsset", (asset) => { this.store.dispatch(addIslandAsset(asset)})) } connectTelemetryService(): void { diff --git a/background/redux-slices/claim.ts b/background/redux-slices/claim.ts index 9240362cc..dc2a6f23a 100644 --- a/background/redux-slices/claim.ts +++ b/background/redux-slices/claim.ts @@ -25,6 +25,8 @@ import { VOTE_WITH_FRIENDS_ADDRESS, } from "../services/island" import { fromFixedPointNumber } from "../lib/fixed-point" +import { SmartContractFungibleAsset } from "../assets" +import { isSameAsset } from "./utils/asset-utils" export interface DAO { address: string @@ -48,6 +50,7 @@ export interface Referrer { interface ClaimingState { status: string + islandAssets: SmartContractFungibleAsset[] claimed: { [address: HexString]: boolean } @@ -80,6 +83,7 @@ const getDistributorContract = async () => { const initialState: ClaimingState = { status: "idle", + islandAssets: [], claimed: {}, selectedForBonus: null, selectedDelegate: null, @@ -152,6 +156,12 @@ const claimingSlice = createSlice({ nonce, expiry, }), + addIslandAsset: ( + immerState, + { payload: asset }: { payload: SmartContractFungibleAsset }, + ) => { + immerState.islandAssets.push(asset) + }, resetClaimFlow: (immerState) => { immerState.signature = undefined immerState.selectedForBonus = null diff --git a/background/services/island/index.ts b/background/services/island/index.ts index 4b7ac0256..3527dd687 100644 --- a/background/services/island/index.ts +++ b/background/services/island/index.ts @@ -35,6 +35,7 @@ export { ReferrerStats } from "./types" interface Events extends ServiceLifecycleEvents { newEligibility: Eligible newReferral: { referrer: AddressOnNetwork } & ReferrerStats + monitoringTestnetAsset: SmartContractFungibleAsset } /* @@ -91,6 +92,8 @@ export default class IslandService extends BaseService { if (!this.indexingService.isTrackingAsset(TESTNET_TAHO)) { await this.indexingService.addAssetToTrack(TESTNET_TAHO) + + this.emitter.emit("monitoringTestnetAsset", TESTNET_TAHO) } const connectedDeployer = TestnetTahoDeployer.connect(islandProvider) @@ -109,6 +112,9 @@ export default class IslandService extends BaseService { xpAddress, { verified: true }, ) + if (asset !== undefined) { + this.emitter.emit("monitoringTestnetAsset", asset) + } }), ) From 101f4d3cd466e56055c62e0bf0eaccb7f75e7ad8 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Wed, 4 Oct 2023 16:57:09 -0400 Subject: [PATCH 09/17] Display portal banner only if the token has been deployed We achieve this by only marking the token as being tracked when it is detected as having code on-chain. The claim slice then exposes a selector that checks if the TESTNET_TAHO token is in the list of tracked island assets. --- background/redux-slices/claim.ts | 6 ++++++ background/services/island/index.ts | 6 ++++++ ui/components/Wallet/Banner/PortalBanner.tsx | 3 ++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/background/redux-slices/claim.ts b/background/redux-slices/claim.ts index dc2a6f23a..142d07502 100644 --- a/background/redux-slices/claim.ts +++ b/background/redux-slices/claim.ts @@ -438,3 +438,9 @@ export const selectEligibilityLoading = createSelector( (state: { claim: ClaimingState }): ClaimingState => state.claim, (claimState: ClaimingState) => claimState.eligibilityLoading, ) + +export const selectIsTestTahoDeployed = createSelector( + (state: { claim: ClaimingState }): ClaimingState => state.claim, + (claimState: ClaimingState) => + claimState.islandAssets.some((asset) => isSameAsset(asset, TESTNET_TAHO)), +) diff --git a/background/services/island/index.ts b/background/services/island/index.ts index 3527dd687..12e244a5b 100644 --- a/background/services/island/index.ts +++ b/background/services/island/index.ts @@ -90,6 +90,12 @@ export default class IslandService extends BaseService { return } + // Bail if the TAHO contract hasn't been deployed. + if ((await islandProvider.getCode(TESTNET_TAHO.contractAddress)) === "0x") { + logger.debug("TAHO contract not deployed, not setting up The Island...") + return + } + if (!this.indexingService.isTrackingAsset(TESTNET_TAHO)) { await this.indexingService.addAssetToTrack(TESTNET_TAHO) diff --git a/ui/components/Wallet/Banner/PortalBanner.tsx b/ui/components/Wallet/Banner/PortalBanner.tsx index 71513b80e..21bf4a0a7 100644 --- a/ui/components/Wallet/Banner/PortalBanner.tsx +++ b/ui/components/Wallet/Banner/PortalBanner.tsx @@ -3,10 +3,11 @@ import { dismissableItemMarkedAsShown, selectShouldShowDismissableItem, } from "@tallyho/tally-background/redux-slices/ui" +import { selectIsTestTahoDeployed } from "@tallyho/tally-background/redux-slices/claim" import { useBackgroundDispatch, useBackgroundSelector } from "../../../hooks" export default function PortalBanner(): ReactElement | null { - const isTokenDeployed = true // useBackgroundSelector(isTestTahoDeployed) + const isTokenDeployed = useBackgroundSelector(selectIsTestTahoDeployed) const isBannerVisible = useBackgroundSelector( selectShouldShowDismissableItem("testnet-portal-is-open-banner"), ) From 1fbef6dcb1dc6c6f11c387a805c45b84ae9e1349 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Wed, 4 Oct 2023 18:53:39 -0400 Subject: [PATCH 10/17] Cleaning up further messes around missing types and errors --- .env.defaults | 4 +- background/main.ts | 8 +-- background/redux-slices/claim.ts | 13 +++-- background/services/island/index.ts | 82 ++++++++++++++++++----------- background/services/island/types.ts | 5 ++ 5 files changed, 72 insertions(+), 40 deletions(-) diff --git a/.env.defaults b/.env.defaults index 197077886..3bed64f16 100644 --- a/.env.defaults +++ b/.env.defaults @@ -33,5 +33,5 @@ SUPPORT_NFT_SEND=false SUPPORT_THE_ISLAND_TESTNET=false USE_MAINNET_FORK=false ARBITRUM_FORK_RPC=https://rpc.tenderly.co/fork/2fc2cf12-5c58-439f-9b5e-967bfd02191a -TESTNET_TAHO_DEPLOYER_ADDRESS=0x267919C3757561672C5499882D7F64DfeA78D067 -TESTNET_TAHO_ADDRESS=0x267919C3757561672C5499882D7F64DfeA78D067 +TESTNET_TAHO_DEPLOYER_ADDRESS=0xD5986D483827a91EE74cC010eD8070D62922027f +TESTNET_TAHO_ADDRESS=0xa260E36D38761a2745a76DD101dB9C71c7116650 diff --git a/background/main.ts b/background/main.ts index adc33b2c2..60bcfa356 100644 --- a/background/main.ts +++ b/background/main.ts @@ -41,7 +41,7 @@ import { import { HexString, NormalizedEVMAddress } from "./types" import { SignedTransaction } from "./networks" import { AccountBalance, AddressOnNetwork, NameOnNetwork } from "./accounts" -import { Eligible } from "./services/island/types" +import { Eligible, ReferrerStats } from "./services/island/types" import rootReducer from "./redux-slices" import { @@ -58,6 +58,7 @@ import { removeAssetData, } from "./redux-slices/assets" import { + addIslandAsset, setEligibility, setEligibilityLoading, setReferrer, @@ -135,7 +136,6 @@ import { SignatureResponse, TXSignatureResponse, } from "./services/signing" -import { ReferrerStats } from "./services/doggo/db" import { migrateReduxState, REDUX_STATE_VERSION, @@ -1661,7 +1661,9 @@ export default class Main extends BaseService { }, ) - this.islandService.emitter.on("monitoringTestnetAsset", (asset) => { this.store.dispatch(addIslandAsset(asset)})) + this.islandService.emitter.on("monitoringTestnetAsset", (asset) => { + this.store.dispatch(addIslandAsset(asset)) + }) } connectTelemetryService(): void { diff --git a/background/redux-slices/claim.ts b/background/redux-slices/claim.ts index 142d07502..91c0c3517 100644 --- a/background/redux-slices/claim.ts +++ b/background/redux-slices/claim.ts @@ -50,7 +50,7 @@ export interface Referrer { interface ClaimingState { status: string - islandAssets: SmartContractFungibleAsset[] + islandAssets: SmartContractFungibleAsset[] | undefined claimed: { [address: HexString]: boolean } @@ -160,7 +160,11 @@ const claimingSlice = createSlice({ immerState, { payload: asset }: { payload: SmartContractFungibleAsset }, ) => { - immerState.islandAssets.push(asset) + if (immerState.islandAssets === undefined) { + immerState.islandAssets = [asset] + } else { + immerState.islandAssets.push(asset) + } }, resetClaimFlow: (immerState) => { immerState.signature = undefined @@ -191,6 +195,7 @@ const claimingSlice = createSlice({ }) export const { + addIslandAsset, chooseSelectedForBonus, chooseDelegate, setEligibility, @@ -442,5 +447,7 @@ export const selectEligibilityLoading = createSelector( export const selectIsTestTahoDeployed = createSelector( (state: { claim: ClaimingState }): ClaimingState => state.claim, (claimState: ClaimingState) => - claimState.islandAssets.some((asset) => isSameAsset(asset, TESTNET_TAHO)), + claimState.islandAssets?.some((asset) => + isSameAsset(asset, TESTNET_TAHO), + ) ?? false, ) diff --git a/background/services/island/index.ts b/background/services/island/index.ts index 12e244a5b..42940a3ae 100644 --- a/background/services/island/index.ts +++ b/background/services/island/index.ts @@ -1,4 +1,4 @@ -import { BigNumber } from "ethers" +import { BigNumber, ethers } from "ethers" import { ServiceLifecycleEvents, ServiceCreatorFunction } from "../types" import { Eligible, ReferrerStats } from "./types" import BaseService from "../base" @@ -65,7 +65,7 @@ export default class IslandService extends BaseService { schedule: { periodInMinutes: 10, }, - handler: () => this.startMonitoringIfNeeded, + handler: () => this.startMonitoringIfNeeded(), runAtStart: true, }, }) @@ -73,6 +73,7 @@ export default class IslandService extends BaseService { private async startMonitoringIfNeeded(): Promise { if (isDisabled(FeatureFlags.SUPPORT_THE_ISLAND_TESTNET)) { + logger.debug("Island testnet disabled, not setting up The Island...") this.isRelevantMonitoringEnabled = true return } @@ -90,39 +91,56 @@ export default class IslandService extends BaseService { return } - // Bail if the TAHO contract hasn't been deployed. - if ((await islandProvider.getCode(TESTNET_TAHO.contractAddress)) === "0x") { - logger.debug("TAHO contract not deployed, not setting up The Island...") - return - } + try { + // Bail if the TAHO contract hasn't been deployed. + if ( + (await islandProvider.getCode(TESTNET_TAHO.contractAddress)) === "0x" + ) { + logger.debug("TAHO contract not deployed, not setting up The Island...") + return + } - if (!this.indexingService.isTrackingAsset(TESTNET_TAHO)) { - await this.indexingService.addAssetToTrack(TESTNET_TAHO) + if (!(await this.indexingService.isTrackingAsset(TESTNET_TAHO))) { + await this.indexingService.addAssetToTrack(TESTNET_TAHO) - this.emitter.emit("monitoringTestnetAsset", TESTNET_TAHO) - } + this.emitter.emit("monitoringTestnetAsset", TESTNET_TAHO) + } - const connectedDeployer = TestnetTahoDeployer.connect(islandProvider) - await Promise.all( - STARTING_REALM_NAMES.map(async (realmName) => { - const realmAddress = - await connectedDeployer.functions[ - `${realmName.toUpperCase()}_REALM` - ]() - const realmContract = - buildRealmContract(realmAddress).connect(islandProvider) - - const xpAddress = await realmContract.functions.xp() - const asset = await this.indexingService.addTokenToTrackByContract( - ISLAND_NETWORK, - xpAddress, - { verified: true }, - ) - if (asset !== undefined) { - this.emitter.emit("monitoringTestnetAsset", asset) - } - }), - ) + const connectedDeployer = TestnetTahoDeployer.connect(islandProvider) + await Promise.all( + STARTING_REALM_NAMES.map(async (realmName) => { + const realmAddress = + await connectedDeployer.functions[ + `${realmName.toUpperCase()}_REALM` + ]() + const realmContract = buildRealmContract(realmAddress[0]).connect( + islandProvider, + ) + + const xpAddress = (await realmContract.functions.xp())[0] + + if (xpAddress === ethers.constants.AddressZero) { + logger.debug( + `XP token for realm ${realmName} at ${realmAddress} is not yet set, throwing an error to retry tracking later.`, + ) + + throw new Error(`XP token does not exist for realm ${realmAddress}`) + } + + const asset = await this.indexingService.addTokenToTrackByContract( + ISLAND_NETWORK, + xpAddress, + { verified: true }, + ) + if (asset !== undefined) { + this.emitter.emit("monitoringTestnetAsset", asset) + } + }), + ) + } catch (error) { + logger.error("Error setting up monitoring for realms", error) + throw error + } // If all monitoring is enabled successfully, don't try again later. this.isRelevantMonitoringEnabled = true diff --git a/background/services/island/types.ts b/background/services/island/types.ts index 8f84aea03..7389f8254 100644 --- a/background/services/island/types.ts +++ b/background/services/island/types.ts @@ -1,5 +1,10 @@ import { HexString } from "../../types" +export type ReferrerStats = { + bonusTotal: bigint + referredUsers: number +} + export interface Eligible { index: HexString account: HexString From 9a27c5fcebb7bb3d9272af1fde4b44552fb65f50 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Wed, 4 Oct 2023 18:54:27 -0400 Subject: [PATCH 11/17] Always display testnet TAHO if island testnet is enabled We'll want to do this with XP as well most likely, but not yet. --- .../redux-slices/selectors/accountsSelectors.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/background/redux-slices/selectors/accountsSelectors.ts b/background/redux-slices/selectors/accountsSelectors.ts index fb933b4db..d9562d983 100644 --- a/background/redux-slices/selectors/accountsSelectors.ts +++ b/background/redux-slices/selectors/accountsSelectors.ts @@ -13,6 +13,7 @@ import { formatCurrencyAmount, heuristicDesiredDecimalsForUnitPrice, isNetworkBaseAsset, + isSameAsset, isTrustedAsset, } from "../utils/asset-utils" import { @@ -45,6 +46,7 @@ import { AccountSigner, SignerType } from "../../services/signing" import { SignerImportSource } from "../../services/internal-signer" import { assertUnreachable } from "../../lib/utils/type-guards" import { PricesState, selectAssetPricePoint } from "../prices" +import { TESTNET_TAHO } from "../../services/island" // TODO What actual precision do we want here? Probably more than 2 // TODO decimals? Maybe it's configurable? @@ -64,11 +66,13 @@ export const userValueDustThreshold = 2 const shouldForciblyDisplayAsset = ( assetAmount: CompleteAssetAmount, ) => { - const isDoggo = - !isEnabled(FeatureFlags.HIDE_TOKEN_FEATURES) && - assetAmount.asset.symbol === DOGGO.symbol + const isIslandRelated = + (!isEnabled(FeatureFlags.HIDE_TOKEN_FEATURES) && + assetAmount.asset.symbol === DOGGO.symbol) || + (isEnabled(FeatureFlags.SUPPORT_THE_ISLAND_TESTNET) && + isSameAsset(assetAmount.asset, TESTNET_TAHO)) - return isDoggo || isNetworkBaseAsset(assetAmount.asset) + return isIslandRelated || isNetworkBaseAsset(assetAmount.asset) } export function determineAssetDisplayAndVerify( From 79cd0cfa1d843d7dc58cc71f331d3022024e825a Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Wed, 4 Oct 2023 18:54:44 -0400 Subject: [PATCH 12/17] Add verified status and logo for testnet TAHO token --- background/services/island/contracts.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/background/services/island/contracts.ts b/background/services/island/contracts.ts index ef810e254..5af778e10 100644 --- a/background/services/island/contracts.ts +++ b/background/services/island/contracts.ts @@ -1,3 +1,4 @@ +import browser from "webextension-polyfill" import { ethers } from "ethers" import { SmartContractFungibleAsset } from "../../assets" import { WEBSITE_ORIGIN } from "../../constants/website" @@ -23,6 +24,8 @@ export const TESTNET_TAHO: SmartContractFungibleAsset = { metadata: { tokenLists: [], websiteURL: WEBSITE_ORIGIN, + logoURL: browser.runtime.getURL("images/assets/doggo.png"), + verified: true, }, } From 31dcdbe812acceff183e5dc27871f7541f265a88 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Wed, 4 Oct 2023 18:55:36 -0400 Subject: [PATCH 13/17] Correctly include tracked assets in IndexingService asset caching For some reason custom assets started being considered a source of truth for asset tracking, instead of custom assets being used strictly for asset metadata and tracked assets being used for tracking info. Anyway, now we include both and deduplicate in `mergeAssets` as usual. --- background/services/indexing/index.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/background/services/indexing/index.ts b/background/services/indexing/index.ts index d033f3ae1..84c2c2169 100644 --- a/background/services/indexing/index.ts +++ b/background/services/indexing/index.ts @@ -292,6 +292,13 @@ export default class IndexingService extends BaseService { * lists. */ async cacheAssetsForNetwork(network: EVMNetwork): Promise { + // FIXME Somewhere along the line, we started confusing tracked and custom + // FIXME assets as informational data. We pull tracked and then custom + // FIXME assets, but really this should never touch custom assets; all + // FIXME custom assets should be tracked if we want to pull them. + const trackedAssets = (await this.db.getAssetsToTrack()).filter((asset) => + sameNetwork(asset.homeNetwork, network), + ) const customAssets = await this.db.getActiveCustomAssetsByNetworks([ network, ]) @@ -301,6 +308,7 @@ export default class IndexingService extends BaseService { this.cachedAssets[network.chainID] = mergeAssets( [network.baseAsset], + trackedAssets, customAssets, networkAssetsFromLists(network, tokenLists), ) From 26263a8b822db3d19398a3875dd4022dcc8953db Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Wed, 4 Oct 2023 18:55:51 -0400 Subject: [PATCH 14/17] Fix key type for assetsToTrack table in IndexingService IndexedDB --- background/services/indexing/db.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/background/services/indexing/db.ts b/background/services/indexing/db.ts index 27f3e6ad3..e6b23f5b0 100644 --- a/background/services/indexing/db.ts +++ b/background/services/indexing/db.ts @@ -143,7 +143,10 @@ export class IndexingDatabase extends Dexie { * Tokens whose balances should be checked periodically. It might make sense * for this to be tracked against particular accounts in the future. */ - private assetsToTrack!: Dexie.Table + private assetsToTrack!: Dexie.Table< + SmartContractFungibleAsset, + [string, string] + > constructor(options?: DexieOptions) { super("tally/indexing", options) From 12a702505593ed3ea350966682ff5f35669d5c7b Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Wed, 4 Oct 2023 23:04:32 -0400 Subject: [PATCH 15/17] Implement portal banner aligned to styles Notably, rather than using a link, we use a `SharedButton`. This is because the styling is basically the same as `SharedButton`, and `SharedLink` can't currently reproduce that (bummer). It also means link opening has to be implemented via browser.tabs.create :/ --- ui/components/Wallet/Banner/PortalBanner.tsx | 72 +++++++++++++++---- ui/public/images/island/portal-image@2x.png | Bin 0 -> 126145 bytes 2 files changed, 60 insertions(+), 12 deletions(-) create mode 100644 ui/public/images/island/portal-image@2x.png diff --git a/ui/components/Wallet/Banner/PortalBanner.tsx b/ui/components/Wallet/Banner/PortalBanner.tsx index 21bf4a0a7..e929a26f9 100644 --- a/ui/components/Wallet/Banner/PortalBanner.tsx +++ b/ui/components/Wallet/Banner/PortalBanner.tsx @@ -1,10 +1,14 @@ -import React, { ReactElement, useCallback } from "react" +import browser from "webextension-polyfill" +import React, { ReactElement } from "react" import { dismissableItemMarkedAsShown, selectShouldShowDismissableItem, } from "@tallyho/tally-background/redux-slices/ui" import { selectIsTestTahoDeployed } from "@tallyho/tally-background/redux-slices/claim" import { useBackgroundDispatch, useBackgroundSelector } from "../../../hooks" +import SharedButton from "../../Shared/SharedButton" +import SharedIcon from "../../Shared/SharedIcon" +import SharedBanner from "../../Shared/SharedBanner" export default function PortalBanner(): ReactElement | null { const isTokenDeployed = useBackgroundSelector(selectIsTestTahoDeployed) @@ -13,24 +17,68 @@ export default function PortalBanner(): ReactElement | null { ) const dispatch = useBackgroundDispatch() - const dismissBanner = () => + const showIslandAndDismissBanner = () => { + // FIXME Shortcut. We should use a real link here. + browser.tabs.create({ url: "https://island.taho.xyz" }) dispatch(dismissableItemMarkedAsShown("testnet-portal-is-open-banner")) + } if (!isTokenDeployed || !isBannerVisible) { return null } return ( - + Explore The Island{" "} + + + + ) } diff --git a/ui/public/images/island/portal-image@2x.png b/ui/public/images/island/portal-image@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6159f8d1c5c38d47aee7a87d38ba4e8c512c5af1 GIT binary patch literal 126145 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 Date: Thu, 5 Oct 2023 20:37:55 -0700 Subject: [PATCH 16/17] Update testnet deployer and TAHO address to match fork latest --- .env.defaults | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.defaults b/.env.defaults index 3bed64f16..3b9fdf5fc 100644 --- a/.env.defaults +++ b/.env.defaults @@ -33,5 +33,5 @@ SUPPORT_NFT_SEND=false SUPPORT_THE_ISLAND_TESTNET=false USE_MAINNET_FORK=false ARBITRUM_FORK_RPC=https://rpc.tenderly.co/fork/2fc2cf12-5c58-439f-9b5e-967bfd02191a -TESTNET_TAHO_DEPLOYER_ADDRESS=0xD5986D483827a91EE74cC010eD8070D62922027f -TESTNET_TAHO_ADDRESS=0xa260E36D38761a2745a76DD101dB9C71c7116650 +TESTNET_TAHO_DEPLOYER_ADDRESS=0x0ACB7821EC6f2Ca5D8a2Dd5518db2C852A1E2A10 +TESTNET_TAHO_ADDRESS=0xE808174921a73df31756ca0996C1a9E5D9667876 From 12bb0760e894eb486b92625df7a92aa8fdd87eb0 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Thu, 5 Oct 2023 20:38:29 -0700 Subject: [PATCH 17/17] Add realm veTAHOs to island monitored assets This will allow these to show proper token approval screens during transaction signing. --- background/services/island/index.ts | 30 ++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/background/services/island/index.ts b/background/services/island/index.ts index 42940a3ae..8022a2c37 100644 --- a/background/services/island/index.ts +++ b/background/services/island/index.ts @@ -117,9 +117,20 @@ export default class IslandService extends BaseService { islandProvider, ) - const xpAddress = (await realmContract.functions.xp())[0] + const realmVeTahoAddress = (await realmContract.functions.veTaho())[0] + const realmVeAsset = + await this.indexingService.addTokenToTrackByContract( + ISLAND_NETWORK, + realmVeTahoAddress, + { verified: true }, + ) + if (realmVeAsset !== undefined) { + this.emitter.emit("monitoringTestnetAsset", realmVeAsset) + } + + const realmXpAddress = (await realmContract.functions.xp())[0] - if (xpAddress === ethers.constants.AddressZero) { + if (realmXpAddress === ethers.constants.AddressZero) { logger.debug( `XP token for realm ${realmName} at ${realmAddress} is not yet set, throwing an error to retry tracking later.`, ) @@ -127,13 +138,14 @@ export default class IslandService extends BaseService { throw new Error(`XP token does not exist for realm ${realmAddress}`) } - const asset = await this.indexingService.addTokenToTrackByContract( - ISLAND_NETWORK, - xpAddress, - { verified: true }, - ) - if (asset !== undefined) { - this.emitter.emit("monitoringTestnetAsset", asset) + const realmXpAsset = + await this.indexingService.addTokenToTrackByContract( + ISLAND_NETWORK, + realmXpAddress, + { verified: true }, + ) + if (realmXpAsset !== undefined) { + this.emitter.emit("monitoringTestnetAsset", realmXpAsset) } }), )