From 3b14cf3d5fd5cbffe128ab16813a9944e08c8adc Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 1 Oct 2025 21:35:12 +0200 Subject: [PATCH 1/2] feat(app): add config --- app2/src/lib/components/SettingsModal.svelte | 414 ++++++++++++++---- .../lib/components/stake/BalanceCard.svelte | 4 +- .../lib/components/stake/BondComponent.svelte | 40 +- .../components/stake/ProxyDustRecovery.svelte | 41 +- .../stake/QuickWithdrawComponent.svelte | 43 +- .../components/stake/UnbondComponent.svelte | 33 +- .../stake/WithdrawalComponent.svelte | 40 +- app2/src/lib/components/ui/Modal.svelte | 2 +- app2/src/lib/stake/config.svelte.ts | 110 +++++ app2/src/lib/stake/config.ts | 25 -- app2/src/routes/stake/+page.svelte | 26 +- 11 files changed, 569 insertions(+), 209 deletions(-) create mode 100644 app2/src/lib/stake/config.svelte.ts delete mode 100644 app2/src/lib/stake/config.ts diff --git a/app2/src/lib/components/SettingsModal.svelte b/app2/src/lib/components/SettingsModal.svelte index e3d461b762b..175b8fe4479 100644 --- a/app2/src/lib/components/SettingsModal.svelte +++ b/app2/src/lib/components/SettingsModal.svelte @@ -1,9 +1,11 @@ -

Settings

- -
-
- - -
+
+ activeTab = id} + /> +
-
-
+ {#if activeTab === "general"} +
+
- -
- -
+ +
-
- tempShowQuoteTokens = value} - /> -
+
+
+ + +
+ +
-
- tempShowDeveloperChainDetails = value} - /> -
+
+ tempShowQuoteTokens = value} + /> +
-
- tempMainnetOnly = value} - /> -
+
+ tempShowDeveloperChainDetails = value} + /> +
-
- tempShowZeroBalances = value} - /> -
+
+ tempMainnetOnly = value} + /> +
-
- tempShowDeveloperPages = value} - /> -
+
+ tempShowZeroBalances = value} + /> +
-
- tempFilterWhitelist = value} - /> +
+ tempShowDeveloperPages = value} + /> +
+ +
+ tempFilterWhitelist = value} + /> +
+ {:else if activeTab === "lst"} +
+
+ + +
+ +
+
+ + +
+ +
+ + +
+
-
- - +
+
+ + +
+ +
+ + +
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ {/if} + +
+ +
diff --git a/app2/src/lib/components/stake/BalanceCard.svelte b/app2/src/lib/components/stake/BalanceCard.svelte index c72524a03a5..01abf8b878f 100644 --- a/app2/src/lib/components/stake/BalanceCard.svelte +++ b/app2/src/lib/components/stake/BalanceCard.svelte @@ -3,7 +3,7 @@ import Button from "$lib/components/ui/Button.svelte" import Card from "$lib/components/ui/Card.svelte" import Tabs from "$lib/components/ui/Tabs.svelte" import { runPromiseExit$ } from "$lib/runtime" -import { DESTINATION_CHANNEL_ID } from "$lib/stake/config" +import { lstConfig } from "$lib/stake/config.svelte.ts" import { predictProxy } from "$lib/stake/instantiate2" import { wallets as WalletStore } from "$lib/stores/wallets.svelte" import { Utils } from "@unionlabs/sdk" @@ -78,7 +78,7 @@ const proxyDustData = runPromiseExit$(() => { Effect.gen(function*() { const proxy = yield* predictProxy({ path: 0n, - channel: DESTINATION_CHANNEL_ID, + channel: lstConfig.DESTINATION_CHANNEL_ID, sender: address, }) diff --git a/app2/src/lib/components/stake/BondComponent.svelte b/app2/src/lib/components/stake/BondComponent.svelte index c5795376fff..dcd837ff517 100644 --- a/app2/src/lib/components/stake/BondComponent.svelte +++ b/app2/src/lib/components/stake/BondComponent.svelte @@ -6,15 +6,7 @@ import UInput from "$lib/components/ui/UInput.svelte" import { runPromiseExit$ } from "$lib/runtime" import { getWagmiConnectorClient } from "$lib/services/evm/clients" import { switchChain } from "$lib/services/transfer-ucs03-evm/chain" -import { - DESTINATION_CHANNEL_ID, - ETHEREUM_CHAIN_ID, - SOURCE_CHANNEL_ID, - UCS03_EVM_ADDRESS, - UCS03_MINTER_ON_UNION, - UCS03_ZKGM, - UNION_CHAIN_ID, -} from "$lib/stake/config" +import { lstConfig } from "$lib/stake/config.svelte.ts" import { predictProxy } from "$lib/stake/instantiate2" import { type StakingRates } from "$lib/stake/schemas" import { uiStore } from "$lib/stores/ui.svelte" @@ -64,12 +56,11 @@ import { import * as O from "effect/Option" import { graphql } from "gql.tada" import { custom } from "viem" -import { mainnet } from "viem/chains" import QuickAmountButtons from "./QuickAmountButtons.svelte" import SlippageSelector from "./SlippageSelector.svelte" import StatusDisplay from "./StatusDisplay.svelte" -const UCS03_EVM = Ucs05.EvmDisplay.make({ address: UCS03_EVM_ADDRESS }) +const UCS03_EVM = Ucs05.EvmDisplay.make({ address: lstConfig.UCS03_EVM_ADDRESS }) interface Props { evmChain: O.Option @@ -236,11 +227,11 @@ const executeBond = (sender: Ucs05.EvmDisplay, sendAmount: bigint, minMintAmount Effect.gen(function*() { // minMintAmount is already calculated with purchase rate and slippage applied - const ethereumChain = yield* ChainRegistry.byUniversalId(ETHEREUM_CHAIN_ID) - const unionChain = yield* ChainRegistry.byUniversalId(UNION_CHAIN_ID) + const ethereumChain = yield* ChainRegistry.byUniversalId(lstConfig.ETHEREUM_CHAIN_ID) + const unionChain = yield* ChainRegistry.byUniversalId(lstConfig.UNION_CHAIN_ID) const proxy = yield* predictProxy({ path: 0n, - channel: DESTINATION_CHANNEL_ID, + channel: lstConfig.DESTINATION_CHANNEL_ID, sender, }) @@ -282,7 +273,7 @@ const executeBond = (sender: Ucs05.EvmDisplay, sendAmount: bigint, minMintAmount const increaseAllowanceCall = yield* pipe( { increase_allowance: { - spender: UCS03_MINTER_ON_UNION.address, + spender: lstConfig.UCS03_MINTER_ON_UNION.address, amount: minMintAmount, }, } as const, @@ -319,7 +310,7 @@ const executeBond = (sender: Ucs05.EvmDisplay, sendAmount: bigint, minMintAmount Effect.flatMap(Schema.encode(Ucs03.Ucs03WithInstructionFromHex)), Effect.map((instruction) => ({ send: { - channel_id: DESTINATION_CHANNEL_ID, + channel_id: lstConfig.DESTINATION_CHANNEL_ID, timeout_height: 0n, timeout_timestamp, salt, @@ -330,7 +321,7 @@ const executeBond = (sender: Ucs05.EvmDisplay, sendAmount: bigint, minMintAmount Effect.map((msg) => ({ wasm: { execute: { - contract_addr: UCS03_ZKGM.address, + contract_addr: lstConfig.UCS03_ZKGM.address, msg, funds: [], }, @@ -363,7 +354,7 @@ const executeBond = (sender: Ucs05.EvmDisplay, sendAmount: bigint, minMintAmount const request = ZkgmClientRequest.make({ source: ethereumChain, destination: unionChain, - channelId: SOURCE_CHANNEL_ID, + channelId: lstConfig.SOURCE_CHANNEL_ID, ucs03Address: UCS03_EVM.address, instruction: batch, }) @@ -393,7 +384,18 @@ runPromiseExit$(() => bondState = BondState.SwitchingChain() - const VIEM_CHAIN = mainnet + const VIEM_CHAIN = yield* pipe( + evmChain, + Effect.flatMap(chain => + pipe( + chain.toViemChain(), + O.match({ + onNone: () => Effect.fail(new Error("No viem chain available")), + onSome: Effect.succeed, + }), + ) + ), + ) const connectorClient = yield* getWagmiConnectorClient diff --git a/app2/src/lib/components/stake/ProxyDustRecovery.svelte b/app2/src/lib/components/stake/ProxyDustRecovery.svelte index bd48c692fe0..c178d25de73 100644 --- a/app2/src/lib/components/stake/ProxyDustRecovery.svelte +++ b/app2/src/lib/components/stake/ProxyDustRecovery.svelte @@ -3,15 +3,7 @@ import Button from "$lib/components/ui/Button.svelte" import { runPromiseExit$ } from "$lib/runtime" import { getWagmiConnectorClient } from "$lib/services/evm/clients" import { switchChain } from "$lib/services/transfer-ucs03-evm/chain" -import { - DESTINATION_CHANNEL_ID, - ETHEREUM_CHAIN_ID, - SOURCE_CHANNEL_ID, - UCS03_EVM_ADDRESS, - UCS03_MINTER_ON_UNION, - UCS03_ZKGM, - UNION_CHAIN_ID, -} from "$lib/stake/config" +import { lstConfig } from "$lib/stake/config.svelte.ts" import { predictProxy } from "$lib/stake/instantiate2" import { uiStore } from "$lib/stores/ui.svelte" import { wallets as WalletStore } from "$lib/stores/wallets.svelte" @@ -37,7 +29,6 @@ import { extractErrorDetails } from "@unionlabs/sdk/utils/index" import { BigDecimal, Data, Effect, Layer, Match, pipe, Schema } from "effect" import * as O from "effect/Option" import { custom } from "viem" -import { mainnet } from "viem/chains" import StatusDisplay from "./StatusDisplay.svelte" import TokenBalanceRow from "./TokenBalanceRow.svelte" @@ -62,7 +53,7 @@ const JsonFromBase64 = Schema.compose( Schema.parseJson(), ) -const UCS03_EVM = Ucs05.EvmDisplay.make({ address: UCS03_EVM_ADDRESS }) +const UCS03_EVM = Ucs05.EvmDisplay.make({ address: lstConfig.UCS03_EVM_ADDRESS }) // Dust withdrawal state machine type DustWithdrawState = Data.TaggedEnum<{ @@ -131,14 +122,14 @@ const executeDustWithdrawal = ( proxyAddr: string, ) => Effect.gen(function*() { - const ethereumChain = yield* ChainRegistry.byUniversalId(ETHEREUM_CHAIN_ID) - const unionChain = yield* ChainRegistry.byUniversalId(UNION_CHAIN_ID) + const ethereumChain = yield* ChainRegistry.byUniversalId(lstConfig.ETHEREUM_CHAIN_ID) + const unionChain = yield* ChainRegistry.byUniversalId(lstConfig.UNION_CHAIN_ID) // For dust withdrawal, we need to transfer eU from proxy to user's wallet on Union // then send it to Ethereum const proxy = yield* predictProxy({ path: 0n, - channel: DESTINATION_CHANNEL_ID, + channel: lstConfig.DESTINATION_CHANNEL_ID, sender, }) @@ -149,7 +140,7 @@ const executeDustWithdrawal = ( const increaseAllowanceCall = yield* pipe( { increase_allowance: { - spender: UCS03_MINTER_ON_UNION.address, + spender: lstConfig.UCS03_MINTER_ON_UNION.address, amount: dustAmountRaw.toString(), }, } as const, @@ -187,7 +178,7 @@ const executeDustWithdrawal = ( Effect.flatMap(Schema.encode(Ucs03.Ucs03WithInstructionFromHex)), Effect.map((instruction) => ({ send: { - channel_id: DESTINATION_CHANNEL_ID, + channel_id: lstConfig.DESTINATION_CHANNEL_ID, timeout_height: 0n, timeout_timestamp, salt, @@ -198,7 +189,7 @@ const executeDustWithdrawal = ( Effect.map((msg) => ({ wasm: { execute: { - contract_addr: UCS03_ZKGM.address, + contract_addr: lstConfig.UCS03_ZKGM.address, msg, funds: [], }, @@ -224,7 +215,7 @@ const executeDustWithdrawal = ( const request = ZkgmClientRequest.make({ source: ethereumChain, destination: unionChain, - channelId: SOURCE_CHANNEL_ID, + channelId: lstConfig.SOURCE_CHANNEL_ID, ucs03Address: UCS03_EVM.address, instruction: batchInstruction, }) @@ -256,7 +247,19 @@ runPromiseExit$(() => dustWithdrawState = DustWithdrawState.SwitchingChain() - const VIEM_CHAIN = mainnet + const VIEM_CHAIN = yield* pipe( + evmChain, + Effect.flatMap(chain => + pipe( + chain.toViemChain(), + O.match({ + onNone: () => Effect.fail(new Error("No viem chain available")), + onSome: Effect.succeed, + }), + ) + ), + ) + const connectorClient = yield* getWagmiConnectorClient const isSafeWallet = getLastConnectedWalletId() === "safe" diff --git a/app2/src/lib/components/stake/QuickWithdrawComponent.svelte b/app2/src/lib/components/stake/QuickWithdrawComponent.svelte index 617a9619606..4cc2bb7746a 100644 --- a/app2/src/lib/components/stake/QuickWithdrawComponent.svelte +++ b/app2/src/lib/components/stake/QuickWithdrawComponent.svelte @@ -6,6 +6,7 @@ import UInput from "$lib/components/ui/UInput.svelte" import { runPromiseExit$ } from "$lib/runtime" import { getWagmiConnectorClient } from "$lib/services/evm/clients" import { switchChain } from "$lib/services/transfer-ucs03-evm/chain" +import { lstConfig } from "$lib/stake/config.svelte.ts" import { uiStore } from "$lib/stores/ui.svelte" import { wallets as WalletStore } from "$lib/stores/wallets.svelte" import { safeOpts } from "$lib/transfer/shared/services/handlers/safe" @@ -19,7 +20,6 @@ import { extractErrorDetails } from "@unionlabs/sdk/utils/index" import { BigDecimal, Data, Effect, Layer, Match, pipe } from "effect" import * as O from "effect/Option" import { createPublicClient, custom, http } from "viem" -import { mainnet } from "viem/chains" import QuickAmountButtons from "./QuickAmountButtons.svelte" import StatusDisplay from "./StatusDisplay.svelte" @@ -132,9 +132,22 @@ const expectedUAmount = $derived>(pipe( runPromiseExit$(() => shouldCheckActive ? Effect.gen(function*() { + const viemChain = yield* pipe( + evmChain, + Effect.flatMap(chain => + pipe( + chain.toViemChain(), + O.match({ + onNone: () => Effect.fail(new Error("No viem chain available")), + onSome: Effect.succeed, + }), + ) + ), + ) + const publicClient = createPublicClient({ - chain: mainnet, - transport: http("https://rpc.1.ethereum.chain.kitchen"), + chain: viemChain, + transport: http(lstConfig.EVM_RPC_ENDPOINT), }) const active = yield* pipe( @@ -222,7 +235,7 @@ const checkAndSubmitAllowance = (sender: `0x${string}`, sendAmount: bigint) => Effect.tap(() => Effect.sleep("500 millis")), ) -const executeQuickWithdraw = (sender: `0x${string}`, sendAmount: bigint) => +const executeQuickWithdraw = (sender: `0x${string}`, sendAmount: bigint, viemChain: any) => Effect.gen(function*() { quickWithdrawState = QuickWithdrawState.ConfirmingWithdraw() @@ -238,7 +251,7 @@ const executeQuickWithdraw = (sender: `0x${string}`, sendAmount: bigint) => functionName: "withdraw", args: [sendAmount], account: sender, - chain: mainnet, + chain: viemChain, }) quickWithdrawState = QuickWithdrawState.WithdrawSubmitted({ txHash }) @@ -279,7 +292,19 @@ runPromiseExit$(() => quickWithdrawState = QuickWithdrawState.SwitchingChain() - const VIEM_CHAIN = mainnet + const VIEM_CHAIN = yield* pipe( + evmChain, + Effect.flatMap(chain => + pipe( + chain.toViemChain(), + O.match({ + onNone: () => Effect.fail(new Error("No viem chain available")), + onSome: Effect.succeed, + }), + ) + ), + ) + const connectorClient = yield* getWagmiConnectorClient const isSafeWallet = getLastConnectedWalletId() === "safe" @@ -311,7 +336,11 @@ runPromiseExit$(() => Effect.tapError((error) => Effect.logError("Approval flow failed", error)), ) - const { txHash, receivedAmount } = yield* executeQuickWithdraw(sender.address, sendAmount) + const { txHash, receivedAmount } = yield* executeQuickWithdraw( + sender.address, + sendAmount, + VIEM_CHAIN, + ) .pipe( Effect.provide(walletClient), Effect.provide(publicClient), diff --git a/app2/src/lib/components/stake/UnbondComponent.svelte b/app2/src/lib/components/stake/UnbondComponent.svelte index c6a26894412..3d42b2271ba 100644 --- a/app2/src/lib/components/stake/UnbondComponent.svelte +++ b/app2/src/lib/components/stake/UnbondComponent.svelte @@ -6,14 +6,7 @@ import UInput from "$lib/components/ui/UInput.svelte" import { runPromiseExit$ } from "$lib/runtime" import { getWagmiConnectorClient } from "$lib/services/evm/clients" import { switchChain } from "$lib/services/transfer-ucs03-evm/chain" -import { - DESTINATION_CHANNEL_ID, - ETHEREUM_CHAIN_ID, - SOURCE_CHANNEL_ID, - UCS03_EVM_ADDRESS, - UCS03_ZKGM, - UNION_CHAIN_ID, -} from "$lib/stake/config" +import { lstConfig } from "$lib/stake/config.svelte.ts" import { predictProxy } from "$lib/stake/instantiate2" import { type StakingRates, StakingRatesSchema } from "$lib/stake/schemas" import { uiStore } from "$lib/stores/ui.svelte" @@ -58,11 +51,10 @@ import { import * as O from "effect/Option" import { graphql } from "gql.tada" import { custom } from "viem" -import { mainnet } from "viem/chains" import QuickAmountButtons from "./QuickAmountButtons.svelte" import StatusDisplay from "./StatusDisplay.svelte" -const UCS03_EVM = Ucs05.EvmDisplay.make({ address: UCS03_EVM_ADDRESS }) +const UCS03_EVM = Ucs05.EvmDisplay.make({ address: lstConfig.UCS03_EVM_ADDRESS }) interface Props { evmChain: O.Option @@ -218,11 +210,11 @@ const checkAndSubmitAllowance = (sender: Ucs05.EvmDisplay, sendAmount: bigint) = const executeUnbond = (sender: Ucs05.EvmDisplay, sendAmount: bigint) => Effect.gen(function*() { - const ethereumChain = yield* ChainRegistry.byUniversalId(ETHEREUM_CHAIN_ID) - const unionChain = yield* ChainRegistry.byUniversalId(UNION_CHAIN_ID) + const ethereumChain = yield* ChainRegistry.byUniversalId(lstConfig.ETHEREUM_CHAIN_ID) + const unionChain = yield* ChainRegistry.byUniversalId(lstConfig.UNION_CHAIN_ID) const proxy = yield* predictProxy({ path: 0n, - channel: DESTINATION_CHANNEL_ID, + channel: lstConfig.DESTINATION_CHANNEL_ID, sender, }) @@ -301,7 +293,7 @@ const executeUnbond = (sender: Ucs05.EvmDisplay, sendAmount: bigint) => const request = ZkgmClientRequest.make({ source: ethereumChain, destination: unionChain, - channelId: SOURCE_CHANNEL_ID, + channelId: lstConfig.SOURCE_CHANNEL_ID, ucs03Address: UCS03_EVM.address, instruction: batch, }) @@ -331,7 +323,18 @@ runPromiseExit$(() => unbondState = UnbondState.SwitchingChain() - const VIEM_CHAIN = mainnet + const VIEM_CHAIN = yield* pipe( + evmChain, + Effect.flatMap(chain => + pipe( + chain.toViemChain(), + O.match({ + onNone: () => Effect.fail(new Error("No viem chain available")), + onSome: Effect.succeed, + }), + ) + ), + ) const connectorClient = yield* getWagmiConnectorClient diff --git a/app2/src/lib/components/stake/WithdrawalComponent.svelte b/app2/src/lib/components/stake/WithdrawalComponent.svelte index 2acfe9e978d..d590ec99a82 100644 --- a/app2/src/lib/components/stake/WithdrawalComponent.svelte +++ b/app2/src/lib/components/stake/WithdrawalComponent.svelte @@ -4,14 +4,7 @@ import Button from "$lib/components/ui/Button.svelte" import { runPromiseExit$ } from "$lib/runtime" import { getWagmiConnectorClient } from "$lib/services/evm/clients" import { switchChain } from "$lib/services/transfer-ucs03-evm/chain" -import { - DESTINATION_CHANNEL_ID, - ETHEREUM_CHAIN_ID, - SOURCE_CHANNEL_ID, - UCS03_EVM_ADDRESS, - UCS03_ZKGM, - UNION_CHAIN_ID, -} from "$lib/stake/config" +import { lstConfig } from "$lib/stake/config.svelte.ts" import { predictProxy } from "$lib/stake/instantiate2" import { BatchResponseSchema, type UnstakeRequest, UnstakeRequestSchema } from "$lib/stake/schemas" import { uiStore } from "$lib/stores/ui.svelte" @@ -41,10 +34,9 @@ import { BigDecimal, Data, Effect, Layer, Match, pipe, Schema } from "effect" import * as A from "effect/Array" import * as O from "effect/Option" import { custom } from "viem" -import { mainnet } from "viem/chains" import StatusDisplay from "./StatusDisplay.svelte" -const UCS03_EVM = Ucs05.EvmDisplay.make({ address: UCS03_EVM_ADDRESS }) +const UCS03_EVM = Ucs05.EvmDisplay.make({ address: lstConfig.UCS03_EVM_ADDRESS }) interface Props { evmChain: O.Option @@ -91,7 +83,7 @@ const withdrawalData = runPromiseExit$(() => { Effect.gen(function*() { const proxy = yield* predictProxy({ path: 0n, - channel: DESTINATION_CHANNEL_ID, + channel: lstConfig.DESTINATION_CHANNEL_ID, sender: address, }) @@ -208,11 +200,11 @@ const executeWithdraw = ( batches: Array<{ batchId: string; withdrawableAmount: BigDecimal.BigDecimal }>, ) => Effect.gen(function*() { - const ethereumChain = yield* ChainRegistry.byUniversalId(ETHEREUM_CHAIN_ID) - const unionChain = yield* ChainRegistry.byUniversalId(UNION_CHAIN_ID) + const ethereumChain = yield* ChainRegistry.byUniversalId(lstConfig.ETHEREUM_CHAIN_ID) + const unionChain = yield* ChainRegistry.byUniversalId(lstConfig.UNION_CHAIN_ID) const proxy = yield* predictProxy({ path: 0n, - channel: DESTINATION_CHANNEL_ID, + channel: lstConfig.DESTINATION_CHANNEL_ID, sender, }) @@ -270,7 +262,7 @@ const executeWithdraw = ( Effect.flatMap(Schema.encode(Ucs03.Ucs03WithInstructionFromHex)), Effect.map((instruction) => ({ send: { - channel_id: DESTINATION_CHANNEL_ID, + channel_id: lstConfig.DESTINATION_CHANNEL_ID, timeout_height: 0n, timeout_timestamp, salt, @@ -281,7 +273,7 @@ const executeWithdraw = ( Effect.map((msg) => ({ wasm: { execute: { - contract_addr: UCS03_ZKGM.address, + contract_addr: lstConfig.UCS03_ZKGM.address, msg, funds: [ { denom: "au", amount: totalAmount }, @@ -311,7 +303,7 @@ const executeWithdraw = ( const request = ZkgmClientRequest.make({ source: ethereumChain, destination: unionChain, - channelId: SOURCE_CHANNEL_ID, + channelId: lstConfig.SOURCE_CHANNEL_ID, ucs03Address: UCS03_EVM.address, instruction: batchInstruction, }) @@ -343,7 +335,19 @@ runPromiseExit$(() => withdrawalState = WithdrawalState.Loading() - const VIEM_CHAIN = mainnet + const VIEM_CHAIN = yield* pipe( + evmChain, + Effect.flatMap(chain => + pipe( + chain.toViemChain(), + O.match({ + onNone: () => Effect.fail(new Error("No viem chain available")), + onSome: Effect.succeed, + }), + ) + ), + ) + const connectorClient = yield* getWagmiConnectorClient const isSafeWallet = getLastConnectedWalletId() === "safe" diff --git a/app2/src/lib/components/ui/Modal.svelte b/app2/src/lib/components/ui/Modal.svelte index 38b48dbe46c..0ec66337feb 100644 --- a/app2/src/lib/components/ui/Modal.svelte +++ b/app2/src/lib/components/ui/Modal.svelte @@ -79,7 +79,7 @@ const internalOnClose = () => { = { + mainnet: "Mainnet ↔ Union", + sepolia: "Sepolia ↔ Union Testnet", + custom: "Custom", +} + +class LSTConfigState { + ethereumChainId = $state("ethereum.1") + unionChainId = $state("union.union-1") + + sourceChannelId = $state(2) + destinationChannelId = $state(1) + + // EVM RPC Endpoint + evmRpcEndpoint = $state("https://rpc.1.ethereum.chain.kitchen") + + // Union/Cosmos RPC Endpoint + // MAINNET: https://rpc.union.build + // TESTNET: https://rpc.union-testnet-10.union.chain.kitchen + unionRpcEndpoint = $state("https://rpc.union.build") + + ucs03EvmAddress = $state<`0x${string}`>("0x5fbe74a283f7954f10aa04c2edf55578811aeb03") + + // UCS03 Minter on Union + // MAINNET: union150u2vpdtau48c50lntaqgleu8rqfnnuh2u3pzfg7pfcvw4uzq6tqceagxy + // TESTNET: union1t5awl707x54k6yyx7qfkuqp890dss2pqgwxh07cu44x5lrlvt4rs8hqmk0 + ucs03MinterOnUnion = $state<`${string}1${string}`>("union150u2vpdtau48c50lntaqgleu8rqfnnuh2u3pzfg7pfcvw4uzq6tqceagxy") + + // ZKGM Contract on Union + ucs03Zkgm = $state<`${string}1${string}`>("union1336jj8ertl8h7rdvnz4dh5rqahd09cy0x43guhsxx6xyrztx292qpe64fh") + + // Derived getters that return the proper typed values + get ETHEREUM_CHAIN_ID() { + return UniversalChainId.make(this.ethereumChainId) + } + + get UNION_CHAIN_ID() { + return UniversalChainId.make(this.unionChainId) + } + + get SOURCE_CHANNEL_ID() { + return ChannelId.make(this.sourceChannelId) + } + + get DESTINATION_CHANNEL_ID() { + return ChannelId.make(this.destinationChannelId) + } + + get EVM_RPC_ENDPOINT() { + return this.evmRpcEndpoint + } + + get UNION_RPC_ENDPOINT() { + return this.unionRpcEndpoint + } + + get UCS03_EVM_ADDRESS() { + return this.ucs03EvmAddress + } + + get UCS03_MINTER_ON_UNION() { + return Ucs05.CosmosDisplay.make({ + address: this.ucs03MinterOnUnion, + }) + } + + get UCS03_ZKGM() { + return Ucs05.CosmosDisplay.make({ + address: this.ucs03Zkgm, + }) + } + + loadPredefined(val: LSTConfig) { + Match.value(val).pipe( + Match.when("mainnet", () => { + this.ethereumChainId = "ethereum.1" + this.unionChainId = "union.union-1" + this.sourceChannelId = 2 + this.destinationChannelId = 1 + this.evmRpcEndpoint = "https://rpc.1.ethereum.chain.kitchen" + this.unionRpcEndpoint = "https://rpc.union.build" + this.ucs03EvmAddress = "0x5fbe74a283f7954f10aa04c2edf55578811aeb03" + this.ucs03MinterOnUnion = "union150u2vpdtau48c50lntaqgleu8rqfnnuh2u3pzfg7pfcvw4uzq6tqceagxy" + this.ucs03Zkgm = "union1336jj8ertl8h7rdvnz4dh5rqahd09cy0x43guhsxx6xyrztx292qpe64fh" + }), + Match.when("sepolia", () => { + this.ethereumChainId = "ethereum.11155111" + this.unionChainId = "union.union-testnet-10" + this.sourceChannelId = 3 + this.destinationChannelId = 3 + this.evmRpcEndpoint = "https://rpc.11155111.ethereum.chain.kitchen" + this.unionRpcEndpoint = "https://rpc.union-testnet-10.union.chain.kitchen" + this.ucs03EvmAddress = "0x5fbe74a283f7954f10aa04c2edf55578811aeb03" + this.ucs03MinterOnUnion = "union1t5awl707x54k6yyx7qfkuqp890dss2pqgwxh07cu44x5lrlvt4rs8hqmk0" + this.ucs03Zkgm = "union1336jj8ertl8h7rdvnz4dh5rqahd09cy0x43guhsxx6xyrztx292qpe64fh" + }), + Match.when("custom", () => {}), + Match.exhaustive, + ) + } +} + +export const lstConfig = new LSTConfigState() diff --git a/app2/src/lib/stake/config.ts b/app2/src/lib/stake/config.ts deleted file mode 100644 index 51ed9981ad1..00000000000 --- a/app2/src/lib/stake/config.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Ucs05 } from "@unionlabs/sdk" -import { ChannelId, UniversalChainId } from "@unionlabs/sdk/schema" - -// Chain configuration - MAINNET -export const ETHEREUM_CHAIN_ID = UniversalChainId.make("ethereum.1") -export const UNION_CHAIN_ID = UniversalChainId.make("union.union-1") - -export const SOURCE_CHANNEL_ID = ChannelId.make(2) -export const DESTINATION_CHANNEL_ID = ChannelId.make(1) - -// UCS03 on EVM -// TESTNET (Sepolia): 0x5fbe74a283f7954f10aa04c2edf55578811aeb03 -export const UCS03_EVM_ADDRESS = "0x5fbe74a283f7954f10aa04c2edf55578811aeb03" - -// UCS03 Minter on Union -// MAINNET: union150u2vpdtau48c50lntaqgleu8rqfnnuh2u3pzfg7pfcvw4uzq6tqceagxy -// TESTNET: union1t5awl707x54k6yyx7qfkuqp890dss2pqgwxh07cu44x5lrlvt4rs8hqmk0 -export const UCS03_MINTER_ON_UNION = Ucs05.CosmosDisplay.make({ - address: "union150u2vpdtau48c50lntaqgleu8rqfnnuh2u3pzfg7pfcvw4uzq6tqceagxy", -}) - -// ZKGM Contract on Union -export const UCS03_ZKGM = Ucs05.CosmosDisplay.make({ - address: "union1336jj8ertl8h7rdvnz4dh5rqahd09cy0x43guhsxx6xyrztx292qpe64fh", -}) diff --git a/app2/src/routes/stake/+page.svelte b/app2/src/routes/stake/+page.svelte index c5364fac3ba..c19505a6e35 100644 --- a/app2/src/routes/stake/+page.svelte +++ b/app2/src/routes/stake/+page.svelte @@ -12,7 +12,7 @@ import Sections from "$lib/components/ui/Sections.svelte" import Tabs from "$lib/components/ui/Tabs.svelte" import * as AppRuntime from "$lib/runtime" import { calculateIncentive } from "$lib/services/incentive" -import { ETHEREUM_CHAIN_ID } from "$lib/stake/config" +import { lstConfig } from "$lib/stake/config.svelte.ts" import { StakingRatesSchema } from "$lib/stake/schemas" import { balancesStore as BalanceStore } from "$lib/stores/balances.svelte" import { chains as ChainStore } from "$lib/stores/chains.svelte" @@ -45,8 +45,6 @@ import { onMount } from "svelte" type StakeTab = "bond" | "unbond" | "withdraw" | "instant-exit" type TableFilter = "all" | "bond" | "unbond" | "withdrawal" -const EVM_UNIVERSAL_CHAIN_ID = ETHEREUM_CHAIN_ID - let showInverseRate = $state(false) const QlpConfigProvider = pipe( @@ -59,12 +57,12 @@ const QlpConfigProvider = pipe( ) const uOnEvmToken = $derived(pipe( - TokenStore.getData(EVM_UNIVERSAL_CHAIN_ID), + TokenStore.getData(lstConfig.ETHEREUM_CHAIN_ID), O.flatMap(A.findFirst(xs => Brand.unbranded(xs.denom) === U_ERC20.address.toLowerCase())), )) const eUOnEvmToken = $derived(pipe( - TokenStore.getData(EVM_UNIVERSAL_CHAIN_ID), + TokenStore.getData(lstConfig.ETHEREUM_CHAIN_ID), O.flatMap(A.findFirst(xs => Brand.unbranded(xs.denom) === EU_ERC20.address.toLowerCase())), )) @@ -153,8 +151,10 @@ const incentives = AppRuntime.runPromiseExit$(() => { ) }) -const stakingRates = AppRuntime.runPromiseExit$(() => - Effect.gen(function*() { +const stakingRates = AppRuntime.runPromiseExit$(() => { + const rpcEndpoint = lstConfig.UNION_RPC_ENDPOINT + + return Effect.gen(function*() { return yield* pipe( Cosmos.queryContract( EU_STAKING_HUB, @@ -163,19 +163,23 @@ const stakingRates = AppRuntime.runPromiseExit$(() => }, ), Effect.flatMap(Schema.decodeUnknown(StakingRatesSchema)), - Effect.provide(Cosmos.Client.Live("https://rpc.union.build")), + Effect.provide(Cosmos.Client.Live(rpcEndpoint)), ) }) -) +}) const evmChain = $derived(pipe( ChainStore.data, - O.flatMap(A.findFirst(x => x.universal_chain_id === EVM_UNIVERSAL_CHAIN_ID)), + O.flatMap(A.findFirst(x => x.universal_chain_id === lstConfig.ETHEREUM_CHAIN_ID)), )) onMount(() => { BalanceStore.interruptBalanceFetching() - TokenStore.fetchTokens(EVM_UNIVERSAL_CHAIN_ID) +}) + +$effect(() => { + void lstConfig.ETHEREUM_CHAIN_ID // Track reactivity + TokenStore.fetchTokens(lstConfig.ETHEREUM_CHAIN_ID) }) $effect(() => { From a2e3ccb71794377a4d686e9ae481e50227741e09 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 1 Oct 2025 21:36:58 +0200 Subject: [PATCH 2/2] chore(app): fmt --- app2/src/lib/components/SettingsModal.svelte | 7 ++++++- app2/src/lib/stake/config.svelte.ts | 8 ++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app2/src/lib/components/SettingsModal.svelte b/app2/src/lib/components/SettingsModal.svelte index 175b8fe4479..2cc1df8a5df 100644 --- a/app2/src/lib/components/SettingsModal.svelte +++ b/app2/src/lib/components/SettingsModal.svelte @@ -1,5 +1,10 @@