Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(wallets): Add sanchonet wallet option #2937

Merged
merged 12 commits into from
Dec 12, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {useWalletNavigation} from '../../navigation'
import {COLORS} from '../../theme'
import {useWalletManager} from '../../WalletManager'
import * as HASKELL_SHELLEY from '../../yoroi-wallets/cardano/constants/mainnet/constants'
import * as SANCHONET from '../../yoroi-wallets/cardano/constants/sanchonet/constants'
import * as HASKELL_SHELLEY_TESTNET from '../../yoroi-wallets/cardano/constants/testnet/constants'
import {InvalidState, NetworkError} from '../../yoroi-wallets/cardano/errors'
import {isJormungandr} from '../../yoroi-wallets/cardano/networks'
Expand Down Expand Up @@ -89,6 +90,8 @@ export const WalletSelectionScreen = () => {

<OnlyNightlyShelleyTestnetButton />

<OnlyNightlyShelleySanchonetButton />

<OnlyDevButton />

<PleaseWaitModal title={strings.loadingWallet} spinnerText={strings.pleaseWait} visible={isLoading} />
Expand Down Expand Up @@ -197,6 +200,25 @@ const OnlyNightlyShelleyTestnetButton = () => {
)
}

const OnlyNightlyShelleySanchonetButton = () => {
const navigation = useNavigation()
const strings = useStrings()

if (!isNightly() && !__DEV__) return null

const onPress = () => {
navigation.navigate('new-wallet', {
screen: 'choose-create-restore',
params: {
networkId: SANCHONET.NETWORK_ID,
walletImplementationId: SANCHONET.WALLET_IMPLEMENTATION_ID,
},
})
}

return <Button onPress={onPress} title={`${strings.addWalletButton} (sanchonet)`} style={styles.button} />
}

const OnlyDevButton = () => {
const navigation = useNavigation()

Expand Down
3 changes: 2 additions & 1 deletion apps/wallet-mobile/src/TxHistory/ActionsBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {TxHistoryRouteNavigation} from '../navigation'
import {useSelectedWallet} from '../SelectedWallet'
import {COLORS} from '../theme'
import {useTokenInfo} from '../yoroi-wallets/hooks'
import {isMainnetNetworkId} from '../yoroi-wallets/utils'

const ACTION_PROPS = {
size: 32,
Expand Down Expand Up @@ -62,7 +63,7 @@ export const ActionsBanner = ({disabled = false}: {disabled: boolean}) => {
track.walletPageExchangeBottomSheetClicked()
// banxa doesn't support testnet for the sandbox it needs a mainnet address
const sandboxWallet = env.getString('BANXA_TEST_WALLET')
const isMainnet = wallet.networkId !== 300
const isMainnet = isMainnetNetworkId(wallet.networkId)
const walletAddress = isMainnet ? wallet.externalAddresses[0] : sandboxWallet
const moduleOptions = {isProduction: isMainnet, partner: 'yoroi'} as const
const urlOptions = {
Expand Down
5 changes: 3 additions & 2 deletions apps/wallet-mobile/src/TxHistory/TxHistoryNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {ReceiveScreen} from '../Receive/ReceiveScreen'
import {useSelectedWallet} from '../SelectedWallet'
import {COLORS} from '../theme'
import {useFrontendFees, useStakingKey, useWalletName} from '../yoroi-wallets/hooks'
import {isMainnetNetworkId} from '../yoroi-wallets/utils'
import {ModalInfo} from './ModalInfo'
import {TxDetails} from './TxDetails'
import {TxHistory} from './TxHistory'
Expand All @@ -69,12 +70,12 @@ export const TxHistoryNavigator = () => {

// swap
const {frontendFees} = useFrontendFees(wallet)
const aggregatorTokenId = wallet.networkId !== 300 ? milkTokenId.mainnet : milkTokenId.preprod
const aggregatorTokenId = isMainnetNetworkId(wallet.networkId) ? milkTokenId.mainnet : milkTokenId.preprod
const stakingKey = useStakingKey(wallet)
const swapManager = React.useMemo(() => {
const swapStorage = swapStorageMaker()
const swapApi = swapApiMaker({
isMainnet: wallet.networkId !== 300,
isMainnet: isMainnetNetworkId(wallet.networkId),
stakingKey,
primaryTokenId: wallet.primaryTokenInfo.id,
supportedProviders,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,17 @@ const apiMock: GovernanceApi = {
export const GovernanceNavigator = () => {
const {networkId} = useSelectedWallet()
const strings = useStrings()
const wallet = useSelectedWallet()
const manager = useMemo(
() =>
governanceManagerMaker({
walletId: wallet.id,
networkId,
api: USE_MOCKED_API ? apiMock : governanceApiMaker({networkId}),
cardano: CardanoMobile,
storage: AsyncStorage,
}),
[networkId],
[networkId, wallet.id],
)
return (
<GovernanceProvider manager={manager}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import {Text} from '../../../../../components'
import {COLORS} from '../../../../../theme'
import {useStrings} from '../strings'

// TODO: replace with real link
const LEARN_MORE_LINK = 'https://google.com'
const LEARN_MORE_LINK = ''
Copy link
Collaborator Author

@michaeljscript michaeljscript Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Links will be hidden until we have them ready YOMO-1025


export const LearnMoreLink = () => {
const strings = useStrings()
Expand All @@ -15,6 +14,8 @@ export const LearnMoreLink = () => {
Linking.openURL(LEARN_MORE_LINK)
}

if (LEARN_MORE_LINK.length === 0) return null

return (
<TouchableOpacity style={styles.root} onPress={onPress}>
<Text style={styles.blueText}>{strings.learnMoreAboutGovernance}</Text>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const ConfirmTxScreen = () => {
const wallet = useSelectedWallet()
const params = useUnsafeParams<Routes['confirm-tx']>()
const navigateTo = useNavigateTo()
const {updateLatestGovernanceAction} = useUpdateLatestGovernanceAction()
const {updateLatestGovernanceAction} = useUpdateLatestGovernanceAction(wallet.id)
const {openModal, closeModal} = useModal()

const titles = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ type Props = {
onSubmit?: (drepId: string) => void
}

const FIND_DREPS_LINK = ''
Copy link
Collaborator Author

@michaeljscript michaeljscript Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Links will be hidden until we have them ready YOMO-1025


export const EnterDrepIdModal = ({onSubmit}: Props) => {
const strings = useStrings()
const [drepId, setDrepId] = useState('')
Expand All @@ -22,8 +24,7 @@ export const EnterDrepIdModal = ({onSubmit}: Props) => {
}

const onLinkPress = () => {
// TODO: Add link to DREPs
Linking.openURL('https://google.com')
Linking.openURL(FIND_DREPS_LINK)
}

return (
Expand All @@ -32,11 +33,15 @@ export const EnterDrepIdModal = ({onSubmit}: Props) => {

<Text style={styles.text}>{strings.enterDRepID}</Text>

<Spacer height={24} />
{FIND_DREPS_LINK.length > 0 && (
<>
<Spacer height={24} />

<Text style={[styles.text, styles.link]} onPress={onLinkPress}>
{strings.findDRepHere}
</Text>
<Text style={[styles.text, styles.link]} onPress={onLinkPress}>
{strings.findDRepHere}
</Text>
</>
)}

<Spacer height={24} />

Expand All @@ -48,7 +53,7 @@ export const EnterDrepIdModal = ({onSubmit}: Props) => {
errorText={error?.message}
/>

<Spacer height={24} />
<Spacer fill />

<Button
title={strings.confirm}
Expand All @@ -57,7 +62,7 @@ export const EnterDrepIdModal = ({onSubmit}: Props) => {
onPress={onPress}
/>

<Spacer height={44} />
<Spacer height={24} />
</View>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const HomeScreen = () => {

const lastVotingAction = useLatestConfirmedGovernanceAction(wallet)

const {data: lastSubmittedTx} = useLatestGovernanceAction()
const {data: lastSubmittedTx} = useLatestGovernanceAction(wallet.id)

const isTxPending =
isString(lastSubmittedTx?.txID) && !Object.values(txInfos).some((tx) => tx.id === lastSubmittedTx?.txID)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {COLORS} from '../../../../../theme'
import {NotEnoughMoneyToSendError} from '../../../../../yoroi-wallets/cardano/types'
import {useTokenInfo} from '../../../../../yoroi-wallets/hooks'
import {YoroiEntry} from '../../../../../yoroi-wallets/types'
import {Quantities} from '../../../../../yoroi-wallets/utils'
import {isMainnetNetworkId, Quantities} from '../../../../../yoroi-wallets/utils'
import {createOrderEntry, makePossibleFrontendFeeEntry} from '../../../common/entries'
import {useNavigateTo} from '../../../common/navigation'
import {useStrings} from '../../../common/strings'
Expand Down Expand Up @@ -123,7 +123,7 @@ export const CreateOrder = () => {
datum,
)

const isMainnet = wallet.networkId !== 300
const isMainnet = isMainnetNetworkId(wallet.networkId)
const frontendFee = selectedPoolCalculation.cost.frontendFeeInfo.fee
const frontendFeeDepositAddress = isMainnet
? Config['FRONTEND_FEE_ADDRESS_MAINNET']
Expand Down
17 changes: 13 additions & 4 deletions apps/wallet-mobile/src/yoroi-wallets/cardano/byron/ByronWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
YoroiSignedTx,
YoroiUnsignedTx,
} from '../../types'
import {asQuantity, Quantities} from '../../utils'
import {asQuantity, isMainnetNetworkId, Quantities} from '../../utils'
import {genTimeToSlot} from '../../utils/timeUtils'
import {validatePassword} from '../../utils/validators'
import {WalletMeta} from '../../walletManager'
Expand Down Expand Up @@ -464,7 +464,16 @@ export class ByronWallet implements YoroiWallet {
}

private getBaseNetworkConfig() {
return this.getNetworkConfig().BASE_CONFIG.reduce((acc, next) => Object.assign(acc, next), {})
type Config = {
PROTOCOL_MAGIC?: number
GENESIS_DATE?: string
START_AT: number
SLOTS_PER_EPOCH: number
SLOT_DURATION: number
}

const config: Config[] = this.getNetworkConfig().BASE_CONFIG
return config.reduce((acc, next) => Object.assign(acc, next), {})
}

private getBackendConfig(): BackendConfig {
Expand Down Expand Up @@ -1137,8 +1146,8 @@ export class ByronWallet implements YoroiWallet {
const apiUrl = this.getBackendConfig().TOKEN_INFO_SERVICE
if (!apiUrl) throw new Error('invalid wallet')

const isMainnet = this.networkId === 1
const isTestnet = this.networkId === 300
const isMainnet = isMainnetNetworkId(this.networkId)
const isTestnet = !isMainnet

if ((tokenId === '' || tokenId === 'ADA') && isMainnet) {
return primaryTokenInfo.mainnet
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import {Balance} from '@yoroi/types'

import {DefaultAsset} from '../../../types'
import {COIN_TYPE, COINS_PER_UTXO_WORD, KEY_DEPOSIT, LINEAR_FEE, MINIMUM_UTXO_VAL, POOL_DEPOSIT} from '../common'

export * from '../common'

export const NETWORK_ID = 450
export const API_ROOT = 'https://sanchonet-backend.yoroiwallet.com/api'
export const TOKEN_INFO_SERVICE = 'https://stage-cdn.yoroiwallet.com'

export const BACKEND = {
API_ROOT,
NFT_STORAGE_URL: 'https://validated-nft-images.s3.amazonaws.com',
TOKEN_INFO_SERVICE,
FETCH_UTXOS_MAX_ADDRESSES: 50,
TX_HISTORY_MAX_ADDRESSES: 50,
FILTER_USED_MAX_ADDRESSES: 50,
TX_HISTORY_RESPONSE_LIMIT: 50,
} as const
export const CHAIN_NETWORK_ID = 0

export const IS_MAINNET = false

export const PROTOCOL_MAGIC = 1097911063
export const BASE_CONFIG = {
GENESIS_DATE: '1686789000000',
PROTOCOL_MAGIC,
SLOTS_PER_EPOCH: 432000,
SLOT_DURATION: 20,
START_AT: 0,
} as const
export const BYRON_BASE_CONFIG = {
// byron-era
PROTOCOL_MAGIC,
// aka byron network id
START_AT: 0,
GENESIS_DATE: '1686789000000',
SLOTS_PER_EPOCH: 4320,
SLOT_DURATION: 20,
} as const

export const SHELLEY_BASE_CONFIG = {
GENESIS_DATE: '1686789000000',
PROTOCOL_MAGIC,
// shelley-era
START_AT: 0,
SLOTS_PER_EPOCH: 86400,
SLOT_DURATION: 1,
} as const

const CARDANO_BASE_CONFIG = [BYRON_BASE_CONFIG, SHELLEY_BASE_CONFIG]
export const NETWORK_CONFIG = {
BACKEND,
BASE_CONFIG: CARDANO_BASE_CONFIG,
CHAIN_NETWORK_ID: CHAIN_NETWORK_ID.toString(),
COIN_TYPE,
ENABLED: true,
EXPLORER_URL_FOR_ADDRESS: (address: string) => `https://preprod.cardanoscan.io/address/${address}`,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No sanchonet explorers yet

EXPLORER_URL_FOR_TOKEN: (fingerprint: string) =>
fingerprint.length > 0
? `https://preprod.cardanoscan.io/token/${fingerprint}`
: `https://preprod.cardanoscan.io/tokens`,
CEXPLORER_URL_FOR_TOKEN: (fingerprint: string) =>
fingerprint.length > 0 ? `https://preprod.cexplorer.io/asset/${fingerprint}` : `https://preprod.cexplorer.io/asset`,
EXPLORER_URL_FOR_TX: (txid: string) => `https://preprod.cardanoscan.io/transaction/${txid}`,
POOL_EXPLORER: 'https://adapools.yoroiwallet.com/?source=mobile',
IS_MAINNET,
KEY_DEPOSIT,
LINEAR_FEE,
MARKETING_NAME: 'Cardano Sancho Testnet',
MINIMUM_UTXO_VAL,
NETWORK_ID,
PER_EPOCH_PERCENTAGE_REWARD: 69344,
POOL_DEPOSIT,
PROVIDER_ID: 300,
COINS_PER_UTXO_WORD,
} as const

export const PRIMARY_TOKEN_INFO: Balance.TokenInfo = {
id: '',
name: 'TADA',
description: 'Cardano',
fingerprint: '',
kind: 'ft',
group: '',
icon: '',
ticker: 'TADA',
image: '',
decimals: 6,
symbol: '₳',
metadatas: {},
} as const

export const PRIMARY_TOKEN: DefaultAsset = {
identifier: '',
networkId: NETWORK_ID,
isDefault: true,
metadata: {
type: 'Cardano',
policyId: '',
assetName: '',
numberOfDecimals: 6,
ticker: 'TADA',
longName: null,
maxSupply: '45000000000000000',
},
} as const
7 changes: 6 additions & 1 deletion apps/wallet-mobile/src/yoroi-wallets/cardano/getWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import {WALLET_IMPLEMENTATION_REGISTRY, WalletFactory} from '../types'
import {ByronWallet} from './byron'
import {WALLET_CONFIG, WALLET_CONFIG_24} from './constants/common'
import * as MAINNET from './constants/mainnet/constants'
import * as SANCHONET from './constants/sanchonet/constants'
import * as TESTNET from './constants/testnet/constants'
import {ShelleyWalletMainnet, ShelleyWalletTestnet} from './shelley'
import {ShelleySanchonetWallet, ShelleyWalletMainnet, ShelleyWalletTestnet} from './shelley'

export const getCardanoWalletFactory = ({
networkId,
Expand All @@ -22,6 +23,10 @@ export const getCardanoWalletFactory = ({
[WALLET_CONFIG.WALLET_IMPLEMENTATION_ID]: ShelleyWalletTestnet,
[WALLET_CONFIG_24.WALLET_IMPLEMENTATION_ID]: ShelleyWalletTestnet,
},
[SANCHONET.NETWORK_ID]: /* cardano sanchonet */ {
[WALLET_CONFIG.WALLET_IMPLEMENTATION_ID]: ShelleySanchonetWallet,
[WALLET_CONFIG_24.WALLET_IMPLEMENTATION_ID]: ShelleySanchonetWallet,
},
} as const

return walletMap[networkId]?.[implementationId]
Expand Down
Loading
Loading