Skip to content
Draft
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/chilled-turtles-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cypherock/cysync-core': patch
---

show syncing and failed status icons for token accounts in wallet page
1 change: 1 addition & 0 deletions packages/coin-support-evm/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { getAppletId, setCoinSupportEthersLib } from './utils';
import { setCoinSupportWeb3Lib } from './utils/web3';

export * from './operations/types';
export * from './operations/staking';
export * from './services';

export { updateLogger } from './utils/logger';
Expand Down
1 change: 1 addition & 0 deletions packages/coin-support-evm/src/operations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export * from './signTransaction';
export * from './broadcastTransaction';
export * from './syncAccount';
export * from './formatAddress';
export * from './staking';
80 changes: 80 additions & 0 deletions packages/coin-support-evm/src/operations/staking/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { IPreparedEvmTransaction } from '../transaction';
import {
IHyspEvmPrepareParams,
IHyspEvmApproveRedeemParams,
IHyspEvmRedeemPrepareParams,
} from './types';
import { callHyspBuildEndpoint, buildPreparedTxn } from './utils';

export * from './types';

export const prepareApproveDeposit = async (
params: IHyspEvmPrepareParams,
): Promise<IPreparedEvmTransaction> => {
const { txn, chain, walletAddress, tokenAddress, amount, countryCode } =
params;
const serverTx = await callHyspBuildEndpoint('build/approve-deposit', {
chain,
walletAddress,
tokenAddress,
amount,
...(countryCode ? { countryCode } : {}),
});
return buildPreparedTxn(serverTx, txn);
};

export const prepareDeposit = async (
params: IHyspEvmPrepareParams,
): Promise<IPreparedEvmTransaction> => {
const { txn, chain, walletAddress, tokenAddress, amount, countryCode } =
params;
const serverTx = await callHyspBuildEndpoint('build/deposit', {
chain,
walletAddress,
tokenAddress,
amount,
...(countryCode ? { countryCode } : {}),
});
return buildPreparedTxn(serverTx, txn);
};

export const prepareApproveRedeem = async (
params: IHyspEvmApproveRedeemParams,
): Promise<IPreparedEvmTransaction> => {
const { txn, chain, walletAddress, amount, countryCode } = params;
const serverTx = await callHyspBuildEndpoint('build/approve-redeem', {
chain,
walletAddress,
amount,
...(countryCode ? { countryCode } : {}),
});
return buildPreparedTxn(serverTx, txn);
};

export const prepareRedeemInstant = async (
params: IHyspEvmRedeemPrepareParams,
): Promise<IPreparedEvmTransaction> => {
const { txn, chain, walletAddress, tokenOut, amount, countryCode } = params;
const serverTx = await callHyspBuildEndpoint('build/redeem-instant', {
chain,
walletAddress,
tokenAddress: tokenOut,
amount,
...(countryCode ? { countryCode } : {}),
});
return buildPreparedTxn(serverTx, txn);
};

export const prepareRedeemQueue = async (
params: IHyspEvmRedeemPrepareParams,
): Promise<IPreparedEvmTransaction> => {
const { txn, chain, walletAddress, tokenOut, amount, countryCode } = params;
const serverTx = await callHyspBuildEndpoint('build/redeem-queue', {
chain,
walletAddress,
tokenAddress: tokenOut,
amount,
...(countryCode ? { countryCode } : {}),
});
return buildPreparedTxn(serverTx, txn);
};
40 changes: 40 additions & 0 deletions packages/coin-support-evm/src/operations/staking/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { IDatabase } from '@cypherock/db-interfaces';

import { IPreparedEvmTransaction } from '../transaction';

export type HyspChain = 'eth_mainnet' | 'base';

export interface IHyspEvmPrepareParams {
accountId: string;
db: IDatabase;
txn: IPreparedEvmTransaction;
chain: HyspChain;
walletAddress: string;
tokenAddress: string;
amount: number;
countryCode?: string;
}

// no tokenOut needed, always approves mevUSD
export interface IHyspEvmApproveRedeemParams {
accountId: string;
db: IDatabase;
txn: IPreparedEvmTransaction;
chain: HyspChain;
walletAddress: string;
amount: number;
countryCode?: string;
}

// Used for redeemInstant and redeemQueue (tokenOut required)
export interface IHyspEvmRedeemPrepareParams
extends IHyspEvmApproveRedeemParams {
tokenOut: string;
}

export interface IHyspServerTxParams {
to: string;
data: string;
value: string;
gasLimit: string;
}
39 changes: 39 additions & 0 deletions packages/coin-support-evm/src/operations/staking/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { makePostRequest, BigNumber } from '@cypherock/cysync-utils';

import { IPreparedEvmTransaction } from '../transaction';
import { IHyspServerTxParams } from './types';

const BASE_URL = 'http://localhost:5001/hysp';

export const callHyspBuildEndpoint = async (
path: string,
body: Record<string, unknown>,
): Promise<IHyspServerTxParams> => {
const response = await makePostRequest(`${BASE_URL}/${path}`, body);
return response.data.data as IHyspServerTxParams;
};

export const buildPreparedTxn = (
serverTx: IHyspServerTxParams,
txn: IPreparedEvmTransaction,
): IPreparedEvmTransaction => {
const gasPrice = txn.userInputs.gasPrice ?? txn.staticData.averageGasPrice;
const fee = new BigNumber(serverTx.gasLimit).multipliedBy(gasPrice);

return {
...txn,
userInputs: {
...txn.userInputs,
outputs: [{ address: serverTx.to, amount: serverTx.value, remarks: '' }],
},
computedData: {
output: { address: serverTx.to, amount: serverTx.value },
data: serverTx.data,
fee: fee.toString(10),
gasLimit: serverTx.gasLimit,
gasLimitEstimate: serverTx.gasLimit,
l1Fee: '0',
gasPrice,
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ export const prepareTransaction = async (
currentOutput = sendAllResult.output;
currentTxn = sendAllResult.txn;
feeHastings = BigInt(scToHastings(feeSC));

// update userInput so that the max amount is editable & not reset to 0
txn.userInputs.outputs[0].amount = sendAmountSC;
}

const validationResult = validateBalanceAndFees(
Expand Down
6 changes: 6 additions & 0 deletions packages/cysync-core/src/actions/dialog/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ export const openAddTokenDialog = (props?: AddTokenDialogProps) =>
export const openReceiveDialog = (data?: ReceiveDialogProps) =>
openDialog({ name: 'receive', data });

export const openHyspDialog = (initialAccountId?: string, initialToken?: 'usdc' | 'usdt', initialWalletId?: string) =>
openDialog({
name: 'hyspDialog',
data: initialAccountId ? { initialAccountId, initialToken, initialWalletId } : undefined,
});

export const openSendDialog = (data?: SendDialogProps) =>
openDialog({ name: 'sendDialog', data });

Expand Down
24 changes: 24 additions & 0 deletions packages/cysync-core/src/bgTask/countryTask/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React, { useEffect } from 'react';

import { getUserCountry } from '~/services/countryService';
import logger from '~/utils/logger';

import { setCountryCode, useAppDispatch } from '../..';

export const CountryTask: React.FC = () => {
const dispatch = useAppDispatch();

useEffect(() => {
getUserCountry()
.then(code => {
dispatch(setCountryCode(code));
logger.info('Country detected', { countryCode: code });
})
.catch(e => {
logger.warn('Country detection failed', e as object);
dispatch(setCountryCode(undefined));
});
}, []);

return null;
};
2 changes: 2 additions & 0 deletions packages/cysync-core/src/bgTask/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';

import { AccountSyncTask } from './accountsSync';
import { CountryTask } from './countryTask';
import { DatabaseListener } from './dbListener';
import { DeviceHandlingTask } from './deviceHandlingTask';
import { NetworkPingTask } from './networkTask';
Expand All @@ -19,5 +20,6 @@ export const BackgroundTasks = () => (
<NetworkPingTask />
<NotificationSyncTask />
<VersionSyncTask />
<CountryTask />
</>
);
14 changes: 14 additions & 0 deletions packages/cysync-core/src/components/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { IWallet } from '@cypherock/db-interfaces';
import React, { FC } from 'react';

import {
openHyspDialog,
openReceiveDialog,
openSendDialog,
openWalletConnectDialog,
Expand Down Expand Up @@ -211,6 +212,19 @@ const SideBarComponent: FC = () => {
}
/>
)}
<SideBarItem
text="Earn"
Icon={DollarIcon}
state={getState('earn')}
onClick={() => navigate('earn')}
extraRight={
<Chip $gradient="silver">
<Typography $fontSize={10} $fontWeight="semibold" color="black">
{strings.new}
</Typography>
</Chip>
}
/>
{window.cysyncFeatureFlags.COVER && (
<SideBarItem
text={strings.cypherockCover}
Expand Down
44 changes: 44 additions & 0 deletions packages/cysync-core/src/constants/hysp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { HyspChain } from '@cypherock/coin-support-evm';
import { EvmIdMap } from '@cypherock/coins';

export const MEV_USD_ADDRESS: Record<HyspChain, string> = {
eth_mainnet: '0x548857309BEfb6Fb6F20a9C5A56c9023D892785B',
base: '0xccbad2823328BCcAEa6476Df3Aa529316aB7474A',
};

export const TOKEN_ADDRESSES: Record<
HyspChain,
{ usdc: string; usdt: string | null }
> = {
eth_mainnet: {
usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
usdt: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
},
base: {
usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
usdt: null,
},
};

export const COIN_ID_TO_CHAIN: Partial<Record<string, HyspChain>> = {
[EvmIdMap.ethereum]: 'eth_mainnet',
[EvmIdMap.base]: 'base',
};

export type EarnProtocol = 'midas' | 'kamino';

export interface IStakeableAsset {
parentAssetId: string; // chain: 'ethereum', 'base', 'solana'
assetId: string; // token: 'usdc', 'usdt'
protocol: EarnProtocol;
geoblocked: boolean; // true = hide for blocked countries
}

export const STAKEABLE_ASSETS: IStakeableAsset[] = [
{ parentAssetId: 'ethereum', assetId: 'ethereum:usd-coin', protocol: 'midas', geoblocked: true },
{ parentAssetId: 'ethereum', assetId: 'ethereum:tether', protocol: 'midas', geoblocked: true },
{ parentAssetId: 'base', assetId: 'base:usd-coin', protocol: 'midas', geoblocked: true },
// { parentAssetId: 'solana', assetId: 'solana:usd-coin', protocol: 'kamino', geoblocked: false },
];

export const MIDAS_BLOCKED_COUNTRIES: string[] = [];
4 changes: 4 additions & 0 deletions packages/cysync-core/src/constants/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ const rootRoutes = {
name: 'refer-and-earn',
path: '/refer-and-earn',
},
earn: {
name: 'earn',
path: '/earn',
},
} as const;

export const routes = {
Expand Down
Loading
Loading