Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/orange-shrimps-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@talismn/balances-react": patch
---

chore: prerelease ease-of-migration changes
Original file line number Diff line number Diff line change
Expand Up @@ -134,48 +134,26 @@ const ToAccount = () => {

const onChangeAddress = useCallback(
(address: string | null) => {
if (!address) {
setEvmAddress(null)
setSubstrateAddress(null)
setBtcAddress(null)
return
}
if (!address) return setEvmAddress(null), setSubstrateAddress(null), setBtcAddress(null)

if (isBitcoinAddress(address)) {
setEvmAddress(null)
setSubstrateAddress(null)
setBtcAddress(address)
return
return setEvmAddress(null), setSubstrateAddress(null), setBtcAddress(address)
}

// if address is in keyring, check platform
const account = allAccounts.find((account) => isAddressEqual(account.address, address))
if (account) {
if (isAccountPlatformEthereum(account)) {
setEvmAddress(address)
setSubstrateAddress(null)
setBtcAddress(null)
return
} else {
setEvmAddress(null)
setSubstrateAddress(address)
setBtcAddress(null)
return
return setEvmAddress(address), setSubstrateAddress(null), setBtcAddress(null)
}
return setEvmAddress(null), setSubstrateAddress(address), setBtcAddress(null)
}

// if address is not in keyring, check address format
if (isEthereumAddress(address)) {
setEvmAddress(address)
setSubstrateAddress(null)
setBtcAddress(null)
return
} else {
setEvmAddress(null)
setSubstrateAddress(address)
setBtcAddress(null)
return
return setEvmAddress(address), setSubstrateAddress(null), setBtcAddress(null)
}
return setEvmAddress(null), setSubstrateAddress(address), setBtcAddress(null)
},
[allAccounts, setBtcAddress, setEvmAddress, setSubstrateAddress],
)
Expand Down
15 changes: 11 additions & 4 deletions apps/extension/src/ui/domains/Swap/swaps.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ export const useSetToAddress = () => {
if (!toAsset) return
// when fromAddress, fromAsset or toAsset changes, set toAddress to either fromAddress or null, depending on whether it's compatible with the new toAsset
switch (toAsset?.networkType) {
case "evm":
case "evm": {
// toAddress is already evm, don't change anything (if it's still compatible with this network)
if (
toEvmAddress &&
Expand All @@ -796,7 +796,8 @@ export const useSetToAddress = () => {

// fromAddress is evm, set toAddress to fromAddress
return setToEvmAddress(fromAddress), setToSubstrateAddress(null), setToBtcAddress(null)
case "substrate":
}
case "substrate": {
// toAddress is already substrate, don't change anything (if it's still compatible with this network)
if (
toSubstrateAddress &&
Expand All @@ -811,18 +812,24 @@ export const useSetToAddress = () => {

// fromAddress is substrate, set toAddress to fromAddress
return setToEvmAddress(null), setToSubstrateAddress(fromAddress), setToBtcAddress(null)
case "btc":
}
case "btc": {
// toAddress is already btc, don't change anything
if (toBtcAddress) return

// fromAddress is never btc, always set toAddress to null
return setToEvmAddress(null), setToSubstrateAddress(null), setToBtcAddress(null)
default:
}
case undefined: {
return
}
default: {
// eslint-disable-next-line no-console
console.error(
`networkType ${toAsset?.networkType} not handled in updateSelectedAccountsOnAssetChange`,
)
return setToEvmAddress(null), setToSubstrateAddress(null), setToBtcAddress(null)
}
}
}, [
fromAccount,
Expand Down
37 changes: 16 additions & 21 deletions apps/extension/src/ui/state/networks.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,37 @@
import { bind } from "@react-rxjs/core"
import { DotNetwork, Network, NetworkId, NetworkList } from "@talismn/chaindata-provider"
import { Network, NetworkId, NetworkList } from "@talismn/chaindata-provider"
import { TFunction } from "i18next"
import { fromPairs, groupBy, toPairs } from "lodash-es"
import { combineLatest, map, of } from "rxjs"

import { getNetworks$, getNetworksMapById$ } from "./chaindata"
import { t$ } from "./i18n"

const getDotNetworkType = (network: DotNetwork, networksById: NetworkList, t: TFunction) => {
switch (network.topology.type) {
case "standalone":
return t("Polkadot-SDK Blockchain")
case "relay":
return t("Relay Chain")
case "parachain": {
const getNetworkType = (network: Network, networksById: NetworkList, t: TFunction) => {
// use name that describes the network type
if (network.platform === "ethereum") return t("Ethereum Blockchain")

if (network.platform === "polkadot") {
if (network.topology.type === "relay") return t("Relay Chain")

if (network.topology.type === "parachain") {
const relay = networksById[network.topology.relayId]
return relay?.name ? t("{{name}} Parachain", { name: relay.name }) : t("Parachain")
}

return t("Polkadot-SDK Blockchain")
}

if (network.platform === "solana") return t("Solana Blockchain")

return t("Blockchain")
}

export const [useNetworkDisplayTypesMapById, networkDisplayTypesMapById$] = bind(
combineLatest([getNetworks$(), getNetworksMapById$(), t$]).pipe(
map(([networks, networksById, t]): Record<NetworkId, string | null> => {
return fromPairs(
networks.map((network) => {
// use name that describes the network type
switch (network.platform) {
case "ethereum":
return [network.id, t("Ethereum Blockchain")]
case "polkadot": {
const dotNetwork = network as DotNetwork
return [network.id, getDotNetworkType(dotNetwork, networksById, t)]
}
case "solana":
return [network.id, t("Solana Blockchain")]
}
}),
networks.map((network) => [network.id, getNetworkType(network, networksById, t)]),
)
}),
),
Expand Down
37 changes: 25 additions & 12 deletions packages/balances-react/src/atoms/chaindata.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { DotNetwork, Network, NetworkList, Token, TokenList } from "@talismn/chaindata-provider"
import { firstThenDebounce } from "@talismn/util"
import { atom } from "jotai"
import { atomWithObservable } from "jotai/utils"
Expand All @@ -23,22 +24,34 @@ const filteredChaindataAtom = atom(async (get) => {
const networks = chaindata.networks.filter(
(n) => (enabledNetworkIds?.includes(n.id) || n.isDefault) && (enableTestnets || !n.isTestnet),
)
const networksById = keyBy(networks, (n) => n.id)
const dotNetworksByGenesisHash = keyBy(
networks.filter((n) => n.platform === "polkadot"),
(n) => n.genesisHash,
)

const networkById = keyBy(networks, (n) => n.id)
const tokens = chaindata.tokens.filter(
(token) =>
(enabledTokenIds?.includes(token.id) || token.isDefault) && networkById[token.networkId],
(enabledTokenIds?.includes(token.id) || token.isDefault) && networksById[token.networkId],
)
const tokensById = keyBy(tokens, (t) => t.id)

return { networks, tokens }
})

export const tokensAtom = atom(async (get) => {
const chaindata = await get(filteredChaindataAtom)
return chaindata.tokens
return { networks, networksById, dotNetworksByGenesisHash, tokens, tokensById }
})

export const networksAtom = atom(async (get) => {
const chaindata = await get(filteredChaindataAtom)
return chaindata.networks
})
export const networksAtom = atom<Promise<Network[]>>(
async (get) => (await get(filteredChaindataAtom)).networks,
)
export const networksByIdAtom = atom<Promise<NetworkList>>(
async (get) => (await get(filteredChaindataAtom)).networksById,
)
export const dotNetworksByGenesisHashAtom = atom<Promise<Record<string, DotNetwork>>>(
async (get) => (await get(filteredChaindataAtom)).dotNetworksByGenesisHash,
)

export const tokensAtom = atom<Promise<Token[]>>(
async (get) => (await get(filteredChaindataAtom)).tokens,
)
export const tokensByIdAtom = atom<Promise<TokenList>>(
async (get) => (await get(filteredChaindataAtom)).tokensById,
)
49 changes: 27 additions & 22 deletions packages/balances-react/src/hooks/useChaindata.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,35 @@
import { NetworkId, TokenId } from "@talismn/chaindata-provider"
import {
DotNetwork,
Network,
NetworkId,
NetworkList,
Token,
TokenId,
TokenList,
} from "@talismn/chaindata-provider"
import { useAtomValue } from "jotai"
import { keyBy } from "lodash-es"
import { useMemo } from "react"

import { chaindataAtom } from "../atoms/chaindata"
import {
chaindataAtom,
dotNetworksByGenesisHashAtom,
networksAtom,
networksByIdAtom,
tokensAtom,
tokensByIdAtom,
} from "../atoms/chaindata"
import { chaindataProviderAtom } from "../atoms/chaindataProvider"

export const useChaindataProvider = () => useAtomValue(chaindataProviderAtom)
export const useChaindata = () => useAtomValue(chaindataAtom)

export const useNetworks = () => useChaindata().networks
export const useNetworksById = () => {
const { networks } = useChaindata()
return useMemo(() => keyBy(networks, (n) => n.id), [networks])
}
export const useNetwork = (networkId?: NetworkId) => {
const networksById = useNetworksById()
return networksById[networkId ?? ""] ?? null
}
export const useNetworks = (): Network[] => useAtomValue(networksAtom)
export const useNetworksById = (): NetworkList => useAtomValue(networksByIdAtom)
export const useDotNetworksByGenesisHash = (): Record<string, DotNetwork> =>
useAtomValue(dotNetworksByGenesisHashAtom)
export const useNetwork = (networkId?: NetworkId): Network | null =>
useAtomValue(networksByIdAtom)[networkId ?? ""] ?? null

export const useTokens = () => useChaindata().tokens
export const useTokensById = () => {
const { tokens } = useChaindata()
return useMemo(() => keyBy(tokens, (t) => t.id), [tokens])
}
export const useToken = (tokenId?: TokenId) => {
const tokensById = useTokensById()
return tokensById[tokenId ?? ""] ?? null
}
export const useTokens = (): Token[] => useAtomValue(tokensAtom)
export const useTokensById = (): TokenList => useAtomValue(tokensByIdAtom)
export const useToken = (tokenId?: TokenId): Token | null =>
useAtomValue(tokensByIdAtom)[tokenId ?? ""] ?? null
5 changes: 5 additions & 0 deletions packages/balances-react/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { useSetAtom } from "jotai"
import { ReactNode, useEffect } from "react"

// import { z } from "zod/v4"

import {
coinsApiConfigAtom,
enabledChainsAtom,
enabledTokensAtom,
enableTestnetsAtom,
} from "./atoms/config"

// Use jitless mode for Firefox compatibility
// z.config({ jitless: true })

export {
evmErc20TokenId,
evmNativeTokenId,
Expand Down
26 changes: 9 additions & 17 deletions packages/balances/src/modules/index.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,21 @@
import { EvmErc20BalanceModule } from "./evm-erc20"
import { EvmNativeBalanceModule } from "./evm-native"
import { EvmUniswapV2BalanceModule } from "./evm-uniswapv2"
import { SolNativeBalanceModule } from "./sol-native"
import { SolSplBalanceModule } from "./sol-spl"
import { SubAssetsBalanceModule } from "./substrate-assets"
import { SubDTaoBalanceModule } from "./substrate-dtao"
import { SubForeignAssetsBalanceModule } from "./substrate-foreignassets"
import { SubHydrationBalanceModule } from "./substrate-hydration"
import { SubNativeBalanceModule } from "./substrate-native"
import { SubPsp22BalanceModule } from "./substrate-psp22"
import { SubTokensBalanceModule } from "./substrate-tokens"

export const BALANCE_MODULES = [
SubNativeBalanceModule,
SubAssetsBalanceModule,
// SubAssetsBalanceModule,
SubDTaoBalanceModule,
SubHydrationBalanceModule,
SubForeignAssetsBalanceModule,
SubPsp22BalanceModule,
SubTokensBalanceModule,
EvmErc20BalanceModule,
EvmUniswapV2BalanceModule,
// SubHydrationBalanceModule,
// SubForeignAssetsBalanceModule,
// SubPsp22BalanceModule,
// SubTokensBalanceModule,
// EvmErc20BalanceModule,
// EvmUniswapV2BalanceModule,
EvmNativeBalanceModule,
SolNativeBalanceModule,
SolSplBalanceModule,
// SolSplBalanceModule,
]

export type AnyBalanceModule = (typeof BALANCE_MODULES)[number] // TODO yeet ? should use IBalance
Expand All @@ -36,7 +28,7 @@ export * from "./substrate-native"
export * from "./substrate-assets"
export * from "./substrate-foreignassets"
export * from "./substrate-hydration"
export * from "./substrate-psp22"
// export * from "./substrate-psp22"
export * from "./substrate-tokens"
export * from "./substrate-dtao"

Expand Down
10 changes: 5 additions & 5 deletions packages/balances/src/modules/substrate-psp22/util.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TypeRegistry } from "@polkadot/types"
import { ContractExecResult } from "@polkadot/types/interfaces"
import { u8aConcatStrict, u8aToHex } from "@polkadot/util"
import type { TypeRegistry } from "@polkadot/types"
import type { ContractExecResult } from "@polkadot/types/interfaces"
import { mergeUint8, toHex } from "@polkadot-api/utils"
import { IChainConnectorDot } from "@talismn/chain-connectors"

export const makeContractCaller =
Expand All @@ -22,8 +22,8 @@ export const makeContractCaller =
"ContractExecResult",
await chainConnector.send(chainId, "state_call", [
"ContractsApi_call",
u8aToHex(
u8aConcatStrict([
toHex(
mergeUint8([
// origin
registry.createType("AccountId", callFrom).toU8a(),
// dest
Expand Down
2 changes: 1 addition & 1 deletion packages/chain-connectors/src/dot/ChainConnectorDotStub.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ProviderInterface, ProviderInterfaceCallback } from "@polkadot/rpc-provider/types"
import { WsProvider } from "@polkadot/rpc-provider"
import { ProviderInterface, ProviderInterfaceCallback } from "@polkadot/rpc-provider/types"
import { DotNetwork, DotNetworkId } from "@talismn/chaindata-provider"
import { throwAfter } from "@talismn/util"

Expand Down
2 changes: 1 addition & 1 deletion packages/chain-connectors/src/dot/IChainConnectorDot.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ProviderInterface, ProviderInterfaceCallback } from "@polkadot/rpc-provider/types"
import type { ProviderInterface, ProviderInterfaceCallback } from "@polkadot/rpc-provider/types"
import { DotNetworkId } from "@talismn/chaindata-provider"

export interface IChainConnectorDot {
Expand Down