diff --git a/app/src/androidTest/java/one/mixin/android/StringResourceFormatInstrumentedTest.kt b/app/src/androidTest/java/one/mixin/android/StringResourceFormatInstrumentedTest.kt
index 2ce28ca11c..118d1fd4b7 100644
--- a/app/src/androidTest/java/one/mixin/android/StringResourceFormatInstrumentedTest.kt
+++ b/app/src/androidTest/java/one/mixin/android/StringResourceFormatInstrumentedTest.kt
@@ -166,6 +166,7 @@ class StringResourceFormatInstrumentedTest {
R.string.Avalanche to "Avalanche",
R.string.HyperEVM to "HyperEVM",
R.string.XLayer to "X Layer",
+ R.string.Robinhood to "Robinhood",
R.string.Toncoin to "TON",
)
diff --git a/app/src/main/java/one/mixin/android/Constants.kt b/app/src/main/java/one/mixin/android/Constants.kt
index a05956a2e0..538d37ee93 100644
--- a/app/src/main/java/one/mixin/android/Constants.kt
+++ b/app/src/main/java/one/mixin/android/Constants.kt
@@ -15,6 +15,7 @@ import one.mixin.android.Constants.ChainId.ETHEREUM_CHAIN_ID
import one.mixin.android.Constants.ChainId.LIGHTNING_NETWORK_CHAIN_ID
import one.mixin.android.Constants.ChainId.Optimism
import one.mixin.android.Constants.ChainId.Polygon
+import one.mixin.android.Constants.ChainId.Robinhood
import one.mixin.android.Constants.ChainId.XLayer
import one.mixin.android.Constants.RouteConfig.ROUTE_BOT_USER_ID
import one.mixin.android.net.CustomDns
@@ -274,8 +275,8 @@ object Constants {
}
- val Web3EvmChainIds = listOf(ETHEREUM_CHAIN_ID, Polygon, BinanceSmartChain, Base, Arbitrum, Optimism, Avalanche, ChainId.HyperEVM, XLayer)
- val Web3ChainIds = listOf(ETHEREUM_CHAIN_ID, Polygon, BinanceSmartChain, Base, Arbitrum, Optimism, Avalanche, ChainId.HyperEVM, XLayer)
+ val Web3EvmChainIds = listOf(ETHEREUM_CHAIN_ID, Polygon, BinanceSmartChain, Base, Arbitrum, Optimism, Avalanche, ChainId.HyperEVM, XLayer, Robinhood)
+ val Web3ChainIds = listOf(ETHEREUM_CHAIN_ID, Polygon, BinanceSmartChain, Base, Arbitrum, Optimism, Avalanche, ChainId.HyperEVM, XLayer, Robinhood)
val Web3UtxoChainIds = listOf(BITCOIN_CHAIN_ID, ChainId.PEARL_CHAIN_ID)
object ChainId {
@@ -309,6 +310,8 @@ object Constants {
const val XLayer = "37f5a4d1-905f-3b34-8291-c37438c7dcfc"
+ const val Robinhood = "b304e03d-d004-3102-875b-8266f8407a1a"
+
const val TON_CHAIN_ID = "ef660437-d915-4e27-ad3f-632bfb6ba0ee"
}
@@ -356,7 +359,8 @@ object Constants {
ETHEREUM_CHAIN_ID to "Ethereum",
Base to "Base",
Optimism to "Optimism",
- Arbitrum to "Arbitrum"
+ Arbitrum to "Arbitrum",
+ Robinhood to "Robinhood",
)
val btcAssets = mapOf(
diff --git a/app/src/main/java/one/mixin/android/db/web3/vo/Web3TokenItem.kt b/app/src/main/java/one/mixin/android/db/web3/vo/Web3TokenItem.kt
index 9e45eb2071..e4c9ddcbc4 100644
--- a/app/src/main/java/one/mixin/android/db/web3/vo/Web3TokenItem.kt
+++ b/app/src/main/java/one/mixin/android/db/web3/vo/Web3TokenItem.kt
@@ -90,6 +90,7 @@ data class Web3TokenItem(
chainId == Constants.ChainId.Polygon -> "Polygon"
chainId == Constants.ChainId.BinanceSmartChain -> "BNB Chain"
chainId == Constants.ChainId.XLayer -> "X Layer"
+ chainId == Constants.ChainId.Robinhood -> "Robinhood"
chainId == Constants.ChainId.BITCOIN_CHAIN_ID -> "Bitcoin"
chainId == Constants.ChainId.PEARL_CHAIN_ID -> "Pearl"
chainId == Constants.ChainId.SOLANA_CHAIN_ID -> "Solana"
@@ -199,6 +200,7 @@ fun Web3TokenItem.getChainFromName(): Chain {
chainId == Constants.ChainId.Avalanche -> Chain.Avalanche
chainId == Constants.ChainId.HyperEVM -> Chain.HyperEVM
chainId == Constants.ChainId.XLayer -> Chain.XLayer
+ chainId == Constants.ChainId.Robinhood -> Chain.Robinhood
chainId == Constants.ChainId.SOLANA_CHAIN_ID -> Chain.Solana
chainId == Constants.ChainId.BITCOIN_CHAIN_ID -> Chain.Bitcoin
chainId == Constants.ChainId.PEARL_CHAIN_ID -> Chain.Bitcoin
@@ -226,6 +228,7 @@ fun Web3TokenItem.getChainSymbolFromName(): String {
chainId == Constants.ChainId.BinanceSmartChain -> "BNB"
chainId == Constants.ChainId.Polygon -> "POL"
chainId == Constants.ChainId.XLayer -> "OKB"
+ chainId == Constants.ChainId.Robinhood -> "ETH"
chainId == Constants.ChainId.BITCOIN_CHAIN_ID -> "BTC"
chainId == Constants.ChainId.PEARL_CHAIN_ID -> "PRL"
chainId == Constants.ChainId.SOLANA_CHAIN_ID -> "SOL"
@@ -246,6 +249,7 @@ fun Web3TokenItem.isNativeEvmAsset(): Boolean =
Constants.ChainId.HyperEVM,
Constants.ChainId.BinanceSmartChain,
Constants.ChainId.XLayer,
+ Constants.ChainId.Robinhood,
-> assetKey == "0x0000000000000000000000000000000000000000"
else -> false
}
diff --git a/app/src/main/java/one/mixin/android/extension/ContextExtension.kt b/app/src/main/java/one/mixin/android/extension/ContextExtension.kt
index 7d2c139470..33444b78e1 100644
--- a/app/src/main/java/one/mixin/android/extension/ContextExtension.kt
+++ b/app/src/main/java/one/mixin/android/extension/ContextExtension.kt
@@ -1157,6 +1157,7 @@ fun Fragment.getTipsByAsset(asset: TokenItem) =
Constants.ChainId.Avalanche,
Constants.ChainId.HyperEVM,
Constants.ChainId.XLayer,
+ Constants.ChainId.Robinhood,
-> getString(R.string.deposit_tip_chain, asset.symbol, asset.chainName ?: getChainName(asset.chainId, asset.chainName, asset.assetKey ?: ""))
else -> getString(R.string.deposit_tip_common, asset.symbol)
}
diff --git a/app/src/main/java/one/mixin/android/pay/DepositUri.kt b/app/src/main/java/one/mixin/android/pay/DepositUri.kt
index b8bfb9b89e..5a8af70f22 100644
--- a/app/src/main/java/one/mixin/android/pay/DepositUri.kt
+++ b/app/src/main/java/one/mixin/android/pay/DepositUri.kt
@@ -114,6 +114,16 @@ internal fun generateDepositUri(
}
}
+ ChainId.Robinhood -> {
+ if (assetId == ChainId.Robinhood) {
+ val weiAmount = nativeEvmWeiAmount(cleanAmount)
+ "ethereum:$address@4663?value=$weiAmount"
+ } else {
+ val uint256Amount = erc20Amount(cleanAmount, precision)
+ "ethereum:${assetKey}@4663/transfer?address=$address&amount=$cleanAmount&uint256=$uint256Amount"
+ }
+ }
+
ChainId.Litecoin -> {
"litecoin:$address?amount=$cleanAmount"
}
diff --git a/app/src/main/java/one/mixin/android/pay/Ethereum.kt b/app/src/main/java/one/mixin/android/pay/Ethereum.kt
index af2c564b43..34e616ac0d 100644
--- a/app/src/main/java/one/mixin/android/pay/Ethereum.kt
+++ b/app/src/main/java/one/mixin/android/pay/Ethereum.kt
@@ -148,5 +148,6 @@ private val ethereumChainIdMap by lazy {
8453 to Constants.ChainId.Base,
42161 to Constants.ChainId.Arbitrum,
999 to Constants.ChainId.HyperEVM,
+ 4663 to Constants.ChainId.Robinhood,
)
}
diff --git a/app/src/main/java/one/mixin/android/tip/wc/internal/Chain.kt b/app/src/main/java/one/mixin/android/tip/wc/internal/Chain.kt
index 7a6048e618..7114406d4e 100644
--- a/app/src/main/java/one/mixin/android/tip/wc/internal/Chain.kt
+++ b/app/src/main/java/one/mixin/android/tip/wc/internal/Chain.kt
@@ -36,6 +36,8 @@ sealed class Chain(
object XLayer : Chain(Constants.ChainId.XLayer, "eip155", "196", "0xc4", "X Layer", "OKB", listOf("https://rpc.xlayer.tech"))
+ object Robinhood : Chain(Constants.ChainId.Robinhood, "eip155", "4663", "0x1237", "Robinhood", "ETH", listOf("https://rpc.mainnet.chain.robinhood.com"))
+
object Solana : Chain(
SOLANA_CHAIN_ID,
"solana",
@@ -76,13 +78,14 @@ sealed class Chain(
Avalanche -> Constants.ChainId.Avalanche
HyperEVM -> Constants.ChainId.HyperEVM
XLayer -> Constants.ChainId.XLayer
+ Robinhood -> Constants.ChainId.Robinhood
Solana -> Constants.ChainId.Solana
Bitcoin -> BITCOIN_CHAIN_ID
}
}
// Chain.Blast
-internal val supportChainList = listOf(Chain.Solana, Chain.Bitcoin, Chain.Ethereum, Chain.Base, Chain.BinanceSmartChain, Chain.Polygon, Chain.Optimism, Chain.Arbitrum, Chain.Avalanche, Chain.HyperEVM, Chain.XLayer)
-internal val evmChainList = listOf(Chain.Ethereum, Chain.Base, Chain.BinanceSmartChain, Chain.Polygon, Chain.Optimism, Chain.Arbitrum, Chain.Avalanche, Chain.HyperEVM, Chain.XLayer)
+internal val supportChainList = listOf(Chain.Solana, Chain.Bitcoin, Chain.Ethereum, Chain.Base, Chain.BinanceSmartChain, Chain.Polygon, Chain.Optimism, Chain.Arbitrum, Chain.Avalanche, Chain.HyperEVM, Chain.XLayer, Chain.Robinhood)
+internal val evmChainList = listOf(Chain.Ethereum, Chain.Base, Chain.BinanceSmartChain, Chain.Polygon, Chain.Optimism, Chain.Arbitrum, Chain.Avalanche, Chain.HyperEVM, Chain.XLayer, Chain.Robinhood)
data class WalletConnectAddresses(
val evm: String,
diff --git a/app/src/main/java/one/mixin/android/ui/wallet/DepositFragment.kt b/app/src/main/java/one/mixin/android/ui/wallet/DepositFragment.kt
index bf2a7ac057..6ceafeb2a0 100644
--- a/app/src/main/java/one/mixin/android/ui/wallet/DepositFragment.kt
+++ b/app/src/main/java/one/mixin/android/ui/wallet/DepositFragment.kt
@@ -349,6 +349,7 @@ class DepositFragment : BaseFragment() {
Constants.ChainId.Avalanche,
Constants.ChainId.HyperEVM,
Constants.ChainId.XLayer,
+ Constants.ChainId.Robinhood,
Constants.ChainId.TON_CHAIN_ID -> true
else -> false
diff --git a/app/src/main/java/one/mixin/android/ui/wallet/TokenListBottomSheetDialogFragment.kt b/app/src/main/java/one/mixin/android/ui/wallet/TokenListBottomSheetDialogFragment.kt
index 6b124c908a..d8d9608fb9 100644
--- a/app/src/main/java/one/mixin/android/ui/wallet/TokenListBottomSheetDialogFragment.kt
+++ b/app/src/main/java/one/mixin/android/ui/wallet/TokenListBottomSheetDialogFragment.kt
@@ -26,6 +26,7 @@ import one.mixin.android.Constants.ChainId.ETHEREUM_CHAIN_ID
import one.mixin.android.Constants.ChainId.HyperEVM
import one.mixin.android.Constants.ChainId.Optimism
import one.mixin.android.Constants.ChainId.Polygon
+import one.mixin.android.Constants.ChainId.Robinhood
import one.mixin.android.Constants.ChainId.SOLANA_CHAIN_ID
import one.mixin.android.Constants.ChainId.TON_CHAIN_ID
import one.mixin.android.Constants.ChainId.TRON_CHAIN_ID
@@ -203,6 +204,10 @@ class TokenListBottomSheetDialogFragment : MixinBottomSheetDialogFragment() {
XLayer
}
+ R.id.radio_robinhood -> {
+ Robinhood
+ }
+
else -> {
null
}
diff --git a/app/src/main/java/one/mixin/android/ui/wallet/components/ImportWalletDetailPage.kt b/app/src/main/java/one/mixin/android/ui/wallet/components/ImportWalletDetailPage.kt
index 9e3c1f3447..39ab6f2229 100644
--- a/app/src/main/java/one/mixin/android/ui/wallet/components/ImportWalletDetailPage.kt
+++ b/app/src/main/java/one/mixin/android/ui/wallet/components/ImportWalletDetailPage.kt
@@ -102,6 +102,7 @@ fun ImportWalletDetailPage(
"Avalanche" to Constants.ChainId.Avalanche,
"HyperEVM" to Constants.ChainId.HyperEVM,
"X Layer" to Constants.ChainId.XLayer,
+ "Robinhood" to Constants.ChainId.Robinhood,
"Solana" to Constants.ChainId.SOLANA_CHAIN_ID
)
var expanded by remember { mutableStateOf(false) }
@@ -127,7 +128,7 @@ fun ImportWalletDetailPage(
val isEvmNetwork = when (selectedNetworkName) {
- "Ethereum", "Base", "BSC", "Polygon", "Arbitrum", "Optimism", "Avalanche", "HyperEVM", "X Layer" -> true
+ "Ethereum", "Base", "BSC", "Polygon", "Arbitrum", "Optimism", "Avalanche", "HyperEVM", "X Layer", "Robinhood" -> true
else -> false
}
val isBitcoin: Boolean = selectedNetworkName == "Bitcoin"
diff --git a/app/src/main/java/one/mixin/android/util/ChainNetwork.kt b/app/src/main/java/one/mixin/android/util/ChainNetwork.kt
index 448af4b977..f714d8eadb 100644
--- a/app/src/main/java/one/mixin/android/util/ChainNetwork.kt
+++ b/app/src/main/java/one/mixin/android/util/ChainNetwork.kt
@@ -18,6 +18,7 @@ private val chainNetworks by lazy {
Constants.ChainId.Arbitrum to "Arbitrum",
Constants.ChainId.HyperEVM to "HyperEVM",
Constants.ChainId.XLayer to "X Layer",
+ Constants.ChainId.Robinhood to "Robinhood",
)
}
@@ -45,6 +46,8 @@ fun getChainNetwork(
return "Optimism"
} else if (chainId == Constants.ChainId.XLayer) {
return "X Layer"
+ } else if (chainId == Constants.ChainId.Robinhood) {
+ return "Robinhood"
}
if (assetId == chainId && !bepChains.contains(chainId) && assetId != Constants.ChainId.LIGHTNING_NETWORK_CHAIN_ID) return null
@@ -68,6 +71,7 @@ private val chainNames by lazy {
Constants.ChainId.BinanceSmartChain to "BNB Smart Chain (BEP-20)",
Constants.ChainId.LIGHTNING_NETWORK_CHAIN_ID to "Lightning",
Constants.ChainId.XLayer to "X Layer",
+ Constants.ChainId.Robinhood to "Robinhood",
)
}
diff --git a/app/src/main/java/one/mixin/android/web3/Web3ChainId.kt b/app/src/main/java/one/mixin/android/web3/Web3ChainId.kt
index f762c2e9bd..db011da852 100644
--- a/app/src/main/java/one/mixin/android/web3/Web3ChainId.kt
+++ b/app/src/main/java/one/mixin/android/web3/Web3ChainId.kt
@@ -20,8 +20,9 @@ object Web3ChainId {
const val AvalancheChainId = 43114
const val BlastChainId = 81457
const val HyperEvmChainId = 999
+ const val RobinhoodChainId = 4663
- val eip155ChainIds = listOf(EthChainId, OptimismChainId, BscChainId, PolygonChainId, XLayerChainId, BaseChainId, ArbitrumChainId, AvalancheChainId, BlastChainId, HyperEvmChainId)
+ val eip155ChainIds = listOf(EthChainId, OptimismChainId, BscChainId, PolygonChainId, XLayerChainId, BaseChainId, ArbitrumChainId, AvalancheChainId, BlastChainId, HyperEvmChainId, RobinhoodChainId)
fun getChainType(id: Int): ChainType =
when {
@@ -41,6 +42,7 @@ object Web3ChainId {
ArbitrumChainId -> Chain.Arbitrum
AvalancheChainId -> Chain.Avalanche
HyperEvmChainId -> Chain.HyperEVM
+ RobinhoodChainId -> Chain.Robinhood
else -> Chain.Solana
}
}
diff --git a/app/src/main/java/one/mixin/android/web3/js/Web3Signer.kt b/app/src/main/java/one/mixin/android/web3/js/Web3Signer.kt
index 1cb569eb82..9ad94a2f9c 100644
--- a/app/src/main/java/one/mixin/android/web3/js/Web3Signer.kt
+++ b/app/src/main/java/one/mixin/android/web3/js/Web3Signer.kt
@@ -68,6 +68,7 @@ internal fun findChainByHexReference(hex: String?): Chain? =
Chain.BinanceSmartChain,
Chain.HyperEVM,
Chain.XLayer,
+ Chain.Robinhood,
Chain.Solana,
).firstOrNull { it.hexReference == hex }
@@ -316,6 +317,11 @@ object Web3Signer {
persist()
Result.success(Chain.XLayer.name)
}
+ Chain.Robinhood.hexReference -> {
+ currentChain = Chain.Robinhood
+ persist()
+ Result.success(Chain.Robinhood.name)
+ }
Chain.Solana.hexReference -> {
currentChain = Chain.Solana
currentNetwork = JsSignerNetwork.Solana.name
diff --git a/app/src/main/java/one/mixin/android/web3/receive/Web3TokenListBottomSheetDialogFragment.kt b/app/src/main/java/one/mixin/android/web3/receive/Web3TokenListBottomSheetDialogFragment.kt
index fbd1f3c7ba..dba798b559 100644
--- a/app/src/main/java/one/mixin/android/web3/receive/Web3TokenListBottomSheetDialogFragment.kt
+++ b/app/src/main/java/one/mixin/android/web3/receive/Web3TokenListBottomSheetDialogFragment.kt
@@ -29,6 +29,7 @@ import one.mixin.android.Constants.ChainId.BinanceSmartChain
import one.mixin.android.Constants.ChainId.ETHEREUM_CHAIN_ID
import one.mixin.android.Constants.ChainId.Optimism
import one.mixin.android.Constants.ChainId.Polygon
+import one.mixin.android.Constants.ChainId.Robinhood
import one.mixin.android.Constants.ChainId.SOLANA_CHAIN_ID
import one.mixin.android.Constants.ChainId.TON_CHAIN_ID
import one.mixin.android.Constants.ChainId.XLayer
@@ -170,6 +171,10 @@ class Web3TokenListBottomSheetDialogFragment : MixinBottomSheetDialogFragment()
XLayer
}
+ R.id.radio_robinhood -> {
+ Robinhood
+ }
+
else -> {
null
}
diff --git a/app/src/main/java/one/mixin/android/web3/swap/SwapTokenListBottomSheetDialogFragment.kt b/app/src/main/java/one/mixin/android/web3/swap/SwapTokenListBottomSheetDialogFragment.kt
index 1da43d6910..da36c4c74d 100644
--- a/app/src/main/java/one/mixin/android/web3/swap/SwapTokenListBottomSheetDialogFragment.kt
+++ b/app/src/main/java/one/mixin/android/web3/swap/SwapTokenListBottomSheetDialogFragment.kt
@@ -31,6 +31,7 @@ import one.mixin.android.Constants.ChainId.BinanceSmartChain
import one.mixin.android.Constants.ChainId.ETHEREUM_CHAIN_ID
import one.mixin.android.Constants.ChainId.Optimism
import one.mixin.android.Constants.ChainId.Polygon
+import one.mixin.android.Constants.ChainId.Robinhood
import one.mixin.android.Constants.ChainId.SOLANA_CHAIN_ID
import one.mixin.android.Constants.ChainId.TON_CHAIN_ID
import one.mixin.android.Constants.ChainId.XLayer
@@ -227,6 +228,10 @@ class SwapTokenListBottomSheetDialogFragment : MixinBottomSheetDialogFragment()
XLayer
}
+ R.id.radio_robinhood -> {
+ Robinhood
+ }
+
R.id.radio_toncoin -> {
TON_CHAIN_ID
}
diff --git a/app/src/main/res/layout/fragment_asset_list_bottom_sheet.xml b/app/src/main/res/layout/fragment_asset_list_bottom_sheet.xml
index 4ef4cc4fcd..20fbceca3e 100644
--- a/app/src/main/res/layout/fragment_asset_list_bottom_sheet.xml
+++ b/app/src/main/res/layout/fragment_asset_list_bottom_sheet.xml
@@ -260,6 +260,17 @@
android:text="@string/XLayer"
android:textSize="14sp"
android:textColor="@drawable/radio_button_text_selector" />
+
+
@@ -339,4 +350,4 @@
-
\ No newline at end of file
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index fea21e623b..2a41529d8b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1585,6 +1585,7 @@
Avalanche
HyperEVM
X Layer
+ Robinhood
TON
%1$s Account
Account
diff --git a/app/src/test/java/one/mixin/android/RobinhoodChainClassificationTest.kt b/app/src/test/java/one/mixin/android/RobinhoodChainClassificationTest.kt
new file mode 100644
index 0000000000..594e1c856e
--- /dev/null
+++ b/app/src/test/java/one/mixin/android/RobinhoodChainClassificationTest.kt
@@ -0,0 +1,17 @@
+package one.mixin.android
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class RobinhoodChainClassificationTest {
+ @Test
+ fun robinhoodUsesExpectedMixinChainIdAndEvmClassification() {
+ assertEquals("b304e03d-d004-3102-875b-8266f8407a1a", Constants.ChainId.Robinhood)
+ assertTrue(Constants.ChainId.Robinhood in Constants.Web3EvmChainIds)
+ assertTrue(Constants.ChainId.Robinhood in Constants.Web3ChainIds)
+ assertFalse(Constants.ChainId.Robinhood in Constants.Web3UtxoChainIds)
+ assertEquals("Robinhood", Constants.AssetId.ethAssets[Constants.ChainId.Robinhood])
+ }
+}
diff --git a/app/src/test/java/one/mixin/android/compose/RobinhoodDepositUriTest.kt b/app/src/test/java/one/mixin/android/compose/RobinhoodDepositUriTest.kt
new file mode 100644
index 0000000000..7b8f9904d8
--- /dev/null
+++ b/app/src/test/java/one/mixin/android/compose/RobinhoodDepositUriTest.kt
@@ -0,0 +1,38 @@
+package one.mixin.android.compose
+
+import one.mixin.android.Constants
+import one.mixin.android.pay.generateDepositUri
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class RobinhoodDepositUriTest {
+ @Test
+ fun nativeEthDepositUriUsesRobinhoodChainId() {
+ assertEquals(
+ "ethereum:0x1111111111111111111111111111111111111111@4663?value=1500000000000000000",
+ generateDepositUri(
+ assetId = Constants.ChainId.Robinhood,
+ chainId = Constants.ChainId.Robinhood,
+ assetKey = "0x0000000000000000000000000000000000000000",
+ address = "0x1111111111111111111111111111111111111111",
+ amount = "1.5",
+ precision = 18,
+ ),
+ )
+ }
+
+ @Test
+ fun robinhoodErc20DepositUriUsesTransferCall() {
+ assertEquals(
+ "ethereum:0x2222222222222222222222222222222222222222@4663/transfer?address=0x1111111111111111111111111111111111111111&amount=1.5&uint256=1500000",
+ generateDepositUri(
+ assetId = "token",
+ chainId = Constants.ChainId.Robinhood,
+ assetKey = "0x2222222222222222222222222222222222222222",
+ address = "0x1111111111111111111111111111111111111111",
+ amount = "1.5",
+ precision = 6,
+ ),
+ )
+ }
+}
diff --git a/app/src/test/java/one/mixin/android/db/web3/vo/RobinhoodTokenItemTest.kt b/app/src/test/java/one/mixin/android/db/web3/vo/RobinhoodTokenItemTest.kt
new file mode 100644
index 0000000000..3fa80302fe
--- /dev/null
+++ b/app/src/test/java/one/mixin/android/db/web3/vo/RobinhoodTokenItemTest.kt
@@ -0,0 +1,52 @@
+package one.mixin.android.db.web3.vo
+
+import one.mixin.android.Constants
+import one.mixin.android.crypto.CryptoWalletHelper
+import one.mixin.android.tip.wc.internal.Chain
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class RobinhoodTokenItemTest {
+ @Test
+ fun robinhoodTokenUsesExpectedDisplayAndNativeAssetMetadata() {
+ val nativeToken = token("0x0000000000000000000000000000000000000000")
+ val erc20Token = token("0x1111111111111111111111111111111111111111")
+
+ assertEquals("Robinhood", nativeToken.getChainDisplayName())
+ assertEquals("ETH", nativeToken.getChainSymbolFromName())
+ assertEquals(Chain.Robinhood, nativeToken.getChainFromName())
+ assertTrue(nativeToken.isNativeEvmAsset())
+ assertFalse(erc20Token.isNativeEvmAsset())
+ }
+
+ @Test
+ fun robinhoodReusesEthereumAddressDerivation() {
+ val privateKey = "0000000000000000000000000000000000000000000000000000000000000001"
+
+ assertEquals(
+ CryptoWalletHelper.privateKeyToAddress(privateKey, Constants.ChainId.ETHEREUM_CHAIN_ID),
+ CryptoWalletHelper.privateKeyToAddress(privateKey, Constants.ChainId.Robinhood),
+ )
+ }
+
+ private fun token(assetKey: String) = Web3TokenItem(
+ walletId = "wallet",
+ assetId = Constants.ChainId.Robinhood,
+ chainId = Constants.ChainId.Robinhood,
+ name = "ETH",
+ assetKey = assetKey,
+ symbol = "ETH",
+ iconUrl = "",
+ precision = 18,
+ balance = "0",
+ priceUsd = "0",
+ changeUsd = "0",
+ chainIcon = null,
+ chainName = null,
+ chainSymbol = null,
+ hidden = false,
+ level = 1,
+ )
+}
diff --git a/app/src/test/java/one/mixin/android/pay/RobinhoodEthereumUriTest.kt b/app/src/test/java/one/mixin/android/pay/RobinhoodEthereumUriTest.kt
new file mode 100644
index 0000000000..82705b8b77
--- /dev/null
+++ b/app/src/test/java/one/mixin/android/pay/RobinhoodEthereumUriTest.kt
@@ -0,0 +1,32 @@
+package one.mixin.android.pay
+
+import kotlinx.coroutines.runBlocking
+import one.mixin.android.Constants
+import one.mixin.android.api.response.AddressResponse
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Test
+
+class RobinhoodEthereumUriTest {
+ @Test
+ fun erc681ChainIdResolvesToRobinhood() = runBlocking {
+ val destination = "0x1111111111111111111111111111111111111111"
+ var validatedChainId: String? = null
+
+ val transfer = parseEthereum(
+ url = "ethereum:$destination@4663",
+ validateAddress = { assetId, chainId, address ->
+ validatedChainId = chainId
+ AddressResponse(address, assetId = assetId)
+ },
+ getFee = { _, _ -> emptyList() },
+ findAssetIdByAssetKey = { null },
+ getAssetPrecisionById = { null },
+ balanceCheck = { _, _, _, _ -> },
+ )
+
+ assertNotNull(transfer)
+ assertEquals(Constants.ChainId.Robinhood, validatedChainId)
+ assertEquals(Constants.ChainId.Robinhood, transfer?.assetId)
+ }
+}
diff --git a/app/src/test/java/one/mixin/android/tip/wc/internal/RobinhoodWalletConnectTest.kt b/app/src/test/java/one/mixin/android/tip/wc/internal/RobinhoodWalletConnectTest.kt
new file mode 100644
index 0000000000..3e368d6b5c
--- /dev/null
+++ b/app/src/test/java/one/mixin/android/tip/wc/internal/RobinhoodWalletConnectTest.kt
@@ -0,0 +1,20 @@
+package one.mixin.android.tip.wc.internal
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class RobinhoodWalletConnectTest {
+ @Test
+ fun robinhoodUsesExpectedWalletConnectMetadata() {
+ assertEquals("b304e03d-d004-3102-875b-8266f8407a1a", Chain.Robinhood.assetId)
+ assertEquals("eip155:4663", Chain.Robinhood.chainId)
+ assertEquals("0x1237", Chain.Robinhood.hexReference)
+ assertEquals("Robinhood", Chain.Robinhood.name)
+ assertEquals("ETH", Chain.Robinhood.symbol)
+ assertEquals(Chain.Robinhood.assetId, Chain.Robinhood.getWeb3ChainId())
+ assertEquals(Chain.Robinhood, getChainByChainId("eip155:4663"))
+ assertEquals(Chain.Robinhood, "4663".getChain())
+ assertTrue(Chain.Robinhood in evmChainList)
+ }
+}
diff --git a/app/src/test/java/one/mixin/android/util/RobinhoodChainNetworkTest.kt b/app/src/test/java/one/mixin/android/util/RobinhoodChainNetworkTest.kt
new file mode 100644
index 0000000000..d2259f89ff
--- /dev/null
+++ b/app/src/test/java/one/mixin/android/util/RobinhoodChainNetworkTest.kt
@@ -0,0 +1,13 @@
+package one.mixin.android.util
+
+import one.mixin.android.Constants
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class RobinhoodChainNetworkTest {
+ @Test
+ fun robinhoodFallbacksUseDisplayName() {
+ assertEquals("Robinhood", getChainNetwork("token", Constants.ChainId.Robinhood, "asset-key"))
+ assertEquals("Robinhood", getChainName(Constants.ChainId.Robinhood, null, "asset-key"))
+ }
+}
diff --git a/app/src/test/java/one/mixin/android/web3/RobinhoodChainIdTest.kt b/app/src/test/java/one/mixin/android/web3/RobinhoodChainIdTest.kt
new file mode 100644
index 0000000000..30eeb4b7a4
--- /dev/null
+++ b/app/src/test/java/one/mixin/android/web3/RobinhoodChainIdTest.kt
@@ -0,0 +1,16 @@
+package one.mixin.android.web3
+
+import one.mixin.android.tip.wc.internal.Chain
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class RobinhoodChainIdTest {
+ @Test
+ fun numericChainIdResolvesToRobinhoodEvm() {
+ assertEquals(4663, Web3ChainId.RobinhoodChainId)
+ assertTrue(Web3ChainId.RobinhoodChainId in Web3ChainId.eip155ChainIds)
+ assertEquals(ChainType.ethereum, Web3ChainId.getChainType(Web3ChainId.RobinhoodChainId))
+ assertEquals(Chain.Robinhood, Web3ChainId.getChain(Web3ChainId.RobinhoodChainId))
+ }
+}
diff --git a/app/src/test/java/one/mixin/android/web3/js/RobinhoodSignerNetworkTest.kt b/app/src/test/java/one/mixin/android/web3/js/RobinhoodSignerNetworkTest.kt
new file mode 100644
index 0000000000..469ed101f6
--- /dev/null
+++ b/app/src/test/java/one/mixin/android/web3/js/RobinhoodSignerNetworkTest.kt
@@ -0,0 +1,12 @@
+package one.mixin.android.web3.js
+
+import one.mixin.android.tip.wc.internal.Chain
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class RobinhoodSignerNetworkTest {
+ @Test
+ fun robinhoodHexReferenceResolvesForPersistedChainState() {
+ assertEquals(Chain.Robinhood, findChainByHexReference("0x1237"))
+ }
+}