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
Original file line number Diff line number Diff line change
Expand Up @@ -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",
)

Expand Down
10 changes: 7 additions & 3 deletions app/src/main/java/one/mixin/android/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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"
}

Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"
Expand All @@ -246,6 +249,7 @@ fun Web3TokenItem.isNativeEvmAsset(): Boolean =
Constants.ChainId.HyperEVM,
Constants.ChainId.BinanceSmartChain,
Constants.ChainId.XLayer,
Constants.ChainId.Robinhood,
-> assetKey == "0x0000000000000000000000000000000000000000"
else -> false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/java/one/mixin/android/pay/DepositUri.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/one/mixin/android/pay/Ethereum.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
}
7 changes: 5 additions & 2 deletions app/src/main/java/one/mixin/android/tip/wc/internal/Chain.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -203,6 +204,10 @@ class TokenListBottomSheetDialogFragment : MixinBottomSheetDialogFragment() {
XLayer
}

R.id.radio_robinhood -> {
Robinhood
}

else -> {
null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
Expand All @@ -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"
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/one/mixin/android/util/ChainNetwork.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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",
)
}

Expand Down Expand Up @@ -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
Expand All @@ -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",
)
}

Expand Down
4 changes: 3 additions & 1 deletion app/src/main/java/one/mixin/android/web3/Web3ChainId.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -41,6 +42,7 @@ object Web3ChainId {
ArbitrumChainId -> Chain.Arbitrum
AvalancheChainId -> Chain.Avalanche
HyperEvmChainId -> Chain.HyperEVM
RobinhoodChainId -> Chain.Robinhood
else -> Chain.Solana
}
}
6 changes: 6 additions & 0 deletions app/src/main/java/one/mixin/android/web3/js/Web3Signer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ internal fun findChainByHexReference(hex: String?): Chain? =
Chain.BinanceSmartChain,
Chain.HyperEVM,
Chain.XLayer,
Chain.Robinhood,
Chain.Solana,
).firstOrNull { it.hexReference == hex }

Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -170,6 +171,10 @@ class Web3TokenListBottomSheetDialogFragment : MixinBottomSheetDialogFragment()
XLayer
}

R.id.radio_robinhood -> {
Robinhood
}

else -> {
null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -227,6 +228,10 @@ class SwapTokenListBottomSheetDialogFragment : MixinBottomSheetDialogFragment()
XLayer
}

R.id.radio_robinhood -> {
Robinhood
}

R.id.radio_toncoin -> {
TON_CHAIN_ID
}
Expand Down
13 changes: 12 additions & 1 deletion app/src/main/res/layout/fragment_asset_list_bottom_sheet.xml
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,17 @@
android:text="@string/XLayer"
android:textSize="14sp"
android:textColor="@drawable/radio_button_text_selector" />

<androidx.appcompat.widget.AppCompatRadioButton
android:id="@+id/radio_robinhood"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:background="@drawable/selector_radio"
android:button="@null"
android:text="@string/Robinhood"
android:textSize="14sp"
android:textColor="@drawable/radio_button_text_selector" />
</RadioGroup>
</HorizontalScrollView>

Expand Down Expand Up @@ -339,4 +350,4 @@

</FrameLayout>
</ViewAnimator>
</RelativeLayout>
</RelativeLayout>
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1585,6 +1585,7 @@
<string name="Avalanche" translatable="false">Avalanche</string>
<string name="HyperEVM" translatable="false">HyperEVM</string>
<string name="XLayer" translatable="false">X Layer</string>
<string name="Robinhood" translatable="false">Robinhood</string>
<string name="Toncoin" translatable="false">TON</string>
<string name="web3_account_network">%1$s Account</string>
<string name="web3_account">Account</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -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])
}
}
Original file line number Diff line number Diff line change
@@ -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,
),
)
}
}
Loading