From ca65f234e975fef9ffd5bdfa6b7b563845d4f9ae Mon Sep 17 00:00:00 2001 From: akiraonstarknet Date: Sun, 3 Nov 2024 17:52:18 +0530 Subject: [PATCH 01/22] raffle page text fixes --- src/app/raffle/page.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/raffle/page.tsx b/src/app/raffle/page.tsx index 0b23bf9..a98e41e 100644 --- a/src/app/raffle/page.tsx +++ b/src/app/raffle/page.tsx @@ -87,17 +87,18 @@ const Raffle: NextPage = () => {

3. You have to register if you want to participate. This mean you or - anyone on your behalf will be available t to collect the merch.{' '} + anyone on your behalf will be available to collect the merch.{' '}

4. The rewards will be in the form of exclusive merch reserved for you

5. Selected winners can collect their merch on 13th Nov, from The Fig - lobby, Bangkok + Lobby, Bangkok

- 6. Winners will be announced on our socials everyday + 6. Winners will be announced on our socials (i.e. X, TG, etc.) + everyday

From 400722e0b80e491306feff36cf9b0cb4221d978e Mon Sep 17 00:00:00 2001 From: akiraonstarknet Date: Sun, 3 Nov 2024 18:35:15 +0530 Subject: [PATCH 02/22] enable mobile actions --- src/app/strategy/[strategyId]/_components/Strategy.tsx | 8 +------- src/components/TxButton.tsx | 2 -- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/app/strategy/[strategyId]/_components/Strategy.tsx b/src/app/strategy/[strategyId]/_components/Strategy.tsx index 25de2ad..be36926 100755 --- a/src/app/strategy/[strategyId]/_components/Strategy.tsx +++ b/src/app/strategy/[strategyId]/_components/Strategy.tsx @@ -46,8 +46,6 @@ import { import { StrategyParams } from '../page'; import MyNumber from '@/utils/MyNumber'; import { ExternalLinkIcon } from '@chakra-ui/icons'; -import { isMobile } from 'react-device-detect'; -import CONSTANTS from '@/constants'; const Strategy = ({ params }: StrategyParams) => { const { address } = useAccount(); @@ -247,9 +245,7 @@ const Strategy = ({ params }: StrategyParams) => { ) == 0 ? '-' : `${balData.data.amount.toEtherToFixedDecimals(balData.data.tokenInfo?.displayDecimals || 2)} ${balData.data.tokenInfo?.name}` - : isMobile - ? CONSTANTS.MOBILE_MSG - : 'Connect wallet'} + : 'Connect wallet'} @@ -276,8 +272,6 @@ const Strategy = ({ params }: StrategyParams) => { Your Holdings: {address ? ( - ) : isMobile ? ( - CONSTANTS.MOBILE_MSG ) : ( 'Connect wallet' )} diff --git a/src/components/TxButton.tsx b/src/components/TxButton.tsx index 643de9e..e38eb54 100755 --- a/src/components/TxButton.tsx +++ b/src/components/TxButton.tsx @@ -1,4 +1,3 @@ -import CONSTANTS from '@/constants'; import { referralCodeAtom } from '@/store/referral.store'; import { StrategyTxProps, monitorNewTxAtom } from '@/store/transactions.atom'; import { IStrategyProps, TokenInfo } from '@/strategies/IStrategy'; @@ -101,7 +100,6 @@ export default function TxButton(props: TxButtonProps) { if (!address) return props.text; return ''; } - if (isMobile) return CONSTANTS.MOBILE_MSG; if (!address) return 'Wallet not connected'; return ''; }, [isMobile, address, props]); From 0665bba0a8009be43b240cf711407d539a0171c3 Mon Sep 17 00:00:00 2001 From: akiraonstarknet Date: Mon, 4 Nov 2024 14:43:57 +0530 Subject: [PATCH 03/22] raffle::select winners:: add debug logs --- src/app/api/raffle/luckyWinner/route.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/api/raffle/luckyWinner/route.ts b/src/app/api/raffle/luckyWinner/route.ts index e908b19..16f6004 100644 --- a/src/app/api/raffle/luckyWinner/route.ts +++ b/src/app/api/raffle/luckyWinner/route.ts @@ -6,7 +6,9 @@ export const dynamic = 'force-dynamic'; // static by default, unless reading the export async function GET(request: Request) { const authHeader = request.headers.get('authorization'); + console.log('Authorization header:', authHeader); if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) { + console.error('Unauthorized request'); return new Response('Unauthorized', { status: 401, }); From 7ce7fc3a3f6ffa0e783801317303ca03e9b67dff Mon Sep 17 00:00:00 2001 From: akiraonstarknet Date: Mon, 4 Nov 2024 14:55:38 +0530 Subject: [PATCH 04/22] raffle: add rt post link --- src/app/raffle/_components/share-on-x.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/raffle/_components/share-on-x.tsx b/src/app/raffle/_components/share-on-x.tsx index ce18fd4..5723796 100644 --- a/src/app/raffle/_components/share-on-x.tsx +++ b/src/app/raffle/_components/share-on-x.tsx @@ -81,7 +81,7 @@ const ShareOnX = () => { {}} From 3573b10330ec308b5ab6040eb3d78544268c42c4 Mon Sep 17 00:00:00 2001 From: akiraonstarknet Date: Wed, 6 Nov 2024 20:35:59 +0700 Subject: [PATCH 05/22] add raffle know more link --- src/app/raffle/page.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/app/raffle/page.tsx b/src/app/raffle/page.tsx index a98e41e..15eca74 100644 --- a/src/app/raffle/page.tsx +++ b/src/app/raffle/page.tsx @@ -1,6 +1,7 @@ import { NextPage } from 'next'; import Image from 'next/image'; import React from 'react'; +import { Button } from '@chakra-ui/react'; import ActiveDeposits from './_components/active-deposits'; import RaffleTimer from './_components/raffle-timer'; @@ -21,9 +22,14 @@ const Raffle: NextPage = () => { during Starkspace (Devcon, Bangkok)

- + Date: Wed, 6 Nov 2024 20:16:12 +0530 Subject: [PATCH 06/22] Add dnmm reverse (#101) * temp remove tnc signing validation * add fetchWithRetry for external endpoints * fix haiko api bug * disable sithswap, 10kswap and starkdefi * build fix * re-add fee * add dnmm2 * Add mainnet ETH Sensei XL contracts --- src/constants.ts | 21 +++++++++ src/store/strategies.atoms.ts | 17 ++++++- src/strategies/IStrategy.ts | 8 +++- src/strategies/auto_strk.strat.ts | 5 +- src/strategies/delta_neutral_mm.ts | 26 +++++++---- src/strategies/delta_neutral_mm_2.ts | 68 ++++++++++++++++++++++++++++ 6 files changed, 131 insertions(+), 14 deletions(-) create mode 100644 src/strategies/delta_neutral_mm_2.ts diff --git a/src/constants.ts b/src/constants.ts index 7d645b3..3984b52 100755 --- a/src/constants.ts +++ b/src/constants.ts @@ -62,6 +62,8 @@ const CONSTANTS = { '0x20d5fc4c9df4f943ebb36078e703369c04176ed00accf290e8295b659d2cea6', DeltaNeutralMMETHUSDC: '0x9d23d9b1fa0db8c9d75a1df924c3820e594fc4ab1475695889286f3f6df250', + DeltaNeutralMMETHUSDCXL: + '0x5852a2fa5f3fa08fc8b0b95096792a954009da28e1fa08430bde9e91bf395fe', }, MOBILE_MSG: 'Desktop/Tablet only', }; @@ -100,6 +102,17 @@ export const TOKENS: TokenInfo[] = [ stepAmount: MyNumber.fromEther('10', 18), isERC4626: false, }, + { + token: '0x057146f6409deb4c9fa12866915dd952aa07c1eb2752e451d7f3b042086bdeb8', + name: 'iETH-c', // nostra eth collateral + decimals: 18, + displayDecimals: 2, + logo: CONSTANTS.LOGOS.ETH, + minAmount: MyNumber.fromEther('10', 18), + maxAmount: MyNumber.fromEther('10000', 18), + stepAmount: MyNumber.fromEther('10', 18), + isERC4626: false, + }, { token: '0x1b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1', name: 'zETH', @@ -193,6 +206,14 @@ export const NFTS: NFTInfo[] = [ mainTokenName: 'ETH', }, }, + { + name: 'frmDNMMETHUSDC2', + address: CONSTANTS.CONTRACTS.DeltaNeutralMMETHUSDCXL, + logo: CONSTANTS.LOGOS.ETH, + config: { + mainTokenName: 'ETH', + }, + }, ]; // ? When updating this, ensure there is redirect available for this route diff --git a/src/store/strategies.atoms.ts b/src/store/strategies.atoms.ts index 0cf8488..db032d5 100755 --- a/src/store/strategies.atoms.ts +++ b/src/store/strategies.atoms.ts @@ -10,6 +10,7 @@ import { DeltaNeutralMM } from '@/strategies/delta_neutral_mm'; import Mustache from 'mustache'; import { getTokenInfoFromName } from '@/utils'; import { allPoolsAtomUnSorted } from './protocols'; +import { DeltaNeutralMM2 } from '@/strategies/delta_neutral_mm_2'; export interface StrategyInfo extends IStrategyProps { name: string; @@ -68,7 +69,7 @@ export function getStrategies() { 'USDC', CONSTANTS.CONTRACTS.DeltaNeutralMMETHUSDC, [1, 0.609886, 1, 0.920975, 0.510078], // precomputed factors based on strategy math - StrategyLiveStatus.NEW, + StrategyLiveStatus.ACTIVE, { maxTVL: 1000, }, @@ -87,12 +88,26 @@ export function getStrategies() { }, ); + const deltaNeutralMMETHUSDCReverse = new DeltaNeutralMM2( + getTokenInfoFromName('ETH'), + 'ETH Sensei XL', + Mustache.render(DNMMDescription, { token1: 'ETH', token2: 'USDC' }), + 'USDC', + CONSTANTS.CONTRACTS.DeltaNeutralMMETHUSDCXL, + [1, 0.5846153846, 1, 0.920975, 0.552509], // precomputed factors based on strategy math + StrategyLiveStatus.NEW, + { + maxTVL: 2000, + }, + ); + const strategies: IStrategy[] = [ autoStrkStrategy, autoUSDCStrategy, deltaNeutralMMUSDCETH, deltaNeutralMMETHUSDC, deltaNeutralMMSTRKETH, + deltaNeutralMMETHUSDCReverse, ]; return strategies; diff --git a/src/strategies/IStrategy.ts b/src/strategies/IStrategy.ts index da89d23..2854896 100755 --- a/src/strategies/IStrategy.ts +++ b/src/strategies/IStrategy.ts @@ -1,5 +1,6 @@ import { IDapp } from '@/store/IDapp.store'; import { BalanceResult, getBalanceAtom } from '@/store/balance.atoms'; +import { LendingSpace } from '@/store/lending.base'; import { Category, PoolInfo } from '@/store/pools'; import { zkLend } from '@/store/zklend.store'; import MyNumber from '@/utils/MyNumber'; @@ -254,14 +255,17 @@ export class IStrategy extends IStrategyProps { return eligiblePools; } - filterZkLend(tokenName: string) { + filterTokenByProtocol( + tokenName: string, + protocol: IDapp = zkLend, + ) { return ( pools: PoolInfo[], amount: string, prevActions: StrategyAction[], ) => { return pools.filter( - (p) => p.pool.name == tokenName && p.protocol.name == zkLend.name, + (p) => p.pool.name == tokenName && p.protocol.name == protocol.name, ); }; } diff --git a/src/strategies/auto_strk.strat.ts b/src/strategies/auto_strk.strat.ts index f4aa5eb..48018a7 100755 --- a/src/strategies/auto_strk.strat.ts +++ b/src/strategies/auto_strk.strat.ts @@ -23,6 +23,7 @@ import { getERC20BalanceAtom, } from '@/store/balance.atoms'; import { getPrice, getTokenInfoFromName } from '@/utils'; +import { zkLend } from '@/store/zklend.store'; interface Step { name: string; @@ -73,12 +74,12 @@ export class AutoTokenStrategy extends IStrategy { { name: `Supplies your ${token} to zkLend`, optimizer: this.optimizer, - filter: [this.filterZkLend(this.token.name)], + filter: [this.filterTokenByProtocol(this.token.name, zkLend)], }, { name: `Re-invest your STRK Rewards every 7 days`, optimizer: this.compounder, - filter: [this.filterZkLend('STRK')], + filter: [this.filterTokenByProtocol('STRK', zkLend)], }, ]; const _risks = [...this.risks]; diff --git a/src/strategies/delta_neutral_mm.ts b/src/strategies/delta_neutral_mm.ts index b52d01b..304d46b 100755 --- a/src/strategies/delta_neutral_mm.ts +++ b/src/strategies/delta_neutral_mm.ts @@ -24,6 +24,8 @@ import { getERC20Balance, } from '@/store/balance.atoms'; import { atom } from 'jotai'; +import { IDapp } from '@/store/IDapp.store'; +import { LendingSpace } from '@/store/lending.base'; export class DeltaNeutralMM extends IStrategy { riskFactor = 0.75; @@ -34,6 +36,8 @@ export class DeltaNeutralMM extends IStrategy { readonly stepAmountFactors: number[]; fee_factor = 0.1; // 10% fee + protocol1: IDapp; + protocol2: IDapp; constructor( token: TokenInfo, name: string, @@ -43,6 +47,8 @@ export class DeltaNeutralMM extends IStrategy { stepAmountFactors: number[], liveStatus: StrategyLiveStatus, settings: IStrategySettings, + protocol1: IDapp = zkLend, + protocol2: IDapp = nostraLending, ) { const rewardTokens = [{ logo: CONSTANTS.LOGOS.STRK }]; const nftInfo = NFTS.find( @@ -54,7 +60,7 @@ export class DeltaNeutralMM extends IStrategy { } const holdingTokens: (TokenInfo | NFTInfo)[] = [nftInfo]; super( - `${token.name.toLowerCase()}_sensei`, + name.toLowerCase().replaceAll(' ', '_'), 'DeltaNeutralMM', name, description, @@ -64,25 +70,27 @@ export class DeltaNeutralMM extends IStrategy { settings, ); this.token = token; + this.protocol1 = protocol1; + this.protocol2 = protocol2; this.steps = [ { - name: `Supply's your ${token.name} to zkLend`, + name: `Supply's your ${token.name} to ${protocol1.name}`, optimizer: this.optimizer, filter: [this.filterMainToken], }, { - name: `Borrow ${secondaryTokenName} from zkLend`, + name: `Borrow ${secondaryTokenName} from ${protocol1.name}`, optimizer: this.optimizer, filter: [this.filterSecondaryToken], }, { - name: `Deposit ${secondaryTokenName} to Nostra`, + name: `Deposit ${secondaryTokenName} to ${protocol2.name}`, optimizer: this.optimizer, filter: [this.filterSecondaryToken], }, { - name: `Borrow ${token.name} from Nostra`, + name: `Borrow ${token.name} from ${protocol2.name}`, optimizer: this.optimizer, filter: [this.filterMainToken], }, @@ -94,7 +102,7 @@ export class DeltaNeutralMM extends IStrategy { { name: `Re-invest your STRK Rewards every 7 days (Compound)`, optimizer: this.compounder, - filter: [this.filterZkLend('STRK')], + filter: [this.filterTokenByProtocol('STRK', this.protocol1)], }, ]; @@ -124,8 +132,8 @@ export class DeltaNeutralMM extends IStrategy { ) { const dapp = prevActions.length == 0 || prevActions.length == 4 - ? zkLend - : nostraLending; + ? this.protocol1 + : this.protocol2; return pools.filter( (p) => p.pool.name == this.token.name && p.protocol.name == dapp.name, ); @@ -136,7 +144,7 @@ export class DeltaNeutralMM extends IStrategy { amount: string, prevActions: StrategyAction[], ) { - const dapp = prevActions.length == 1 ? zkLend : nostraLending; + const dapp = prevActions.length == 1 ? this.protocol1 : this.protocol2; return pools.filter( (p) => p.pool.name == this.secondaryToken && p.protocol.name == dapp.name, ); diff --git a/src/strategies/delta_neutral_mm_2.ts b/src/strategies/delta_neutral_mm_2.ts new file mode 100644 index 0000000..4f1bcc1 --- /dev/null +++ b/src/strategies/delta_neutral_mm_2.ts @@ -0,0 +1,68 @@ +import { TokenName } from '@/constants'; +import { DeltaNeutralMM } from './delta_neutral_mm'; +import { IStrategySettings, StrategyLiveStatus, TokenInfo } from './IStrategy'; +import { nostraLending } from '@/store/nostralending.store'; +import { zkLend } from '@/store/zklend.store'; +import MyNumber from '@/utils/MyNumber'; +import { getPrice, getTokenInfoFromName } from '@/utils'; +import { getERC20Balance } from '@/store/balance.atoms'; + +export class DeltaNeutralMM2 extends DeltaNeutralMM { + constructor( + token: TokenInfo, + name: string, + description: string, + secondaryTokenName: TokenName, + strategyAddress: string, + stepAmountFactors: number[], + liveStatus: StrategyLiveStatus, + settings: IStrategySettings, + ) { + super( + token, + name, + description, + secondaryTokenName, + strategyAddress, + stepAmountFactors, + liveStatus, + settings, + nostraLending, + zkLend, + ); + } + + getTVL = async () => { + if (!this.isLive()) + return { + amount: MyNumber.fromEther('0', this.token.decimals), + usdValue: 0, + tokenInfo: this.token, + }; + + try { + const mainTokenName = this.token.name; + const colToken = getTokenInfoFromName(`i${mainTokenName}-c`); + + const bal = await getERC20Balance(colToken, this.strategyAddress); + console.log('getTVL222', bal.amount.toString()); + // This reduces the zToken TVL to near actual deposits made by users wihout looping + const discountFactor = this.stepAmountFactors[4]; + const amount = bal.amount.operate('div', 1 + discountFactor); + console.log('getTVL1', amount.toString()); + const price = await getPrice(this.token); + return { + amount, + usdValue: Number(amount.toEtherStr()) * price, + tokenInfo: this.token, + }; + } catch (error) { + console.error('Error fetching TVL:', error); + return { + amount: MyNumber.fromEther('0', this.token.decimals), + usdValue: 0, + tokenInfo: this.token, + }; + } + }; +} From dd7a83388be616af9532da01e1dca701ae4a76e0 Mon Sep 17 00:00:00 2001 From: akiraonstarknet Date: Wed, 6 Nov 2024 22:16:42 +0700 Subject: [PATCH 07/22] fix haiko api bug --- src/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants.ts b/src/constants.ts index 3984b52..3b7e589 100755 --- a/src/constants.ts +++ b/src/constants.ts @@ -41,7 +41,7 @@ const CONSTANTS = { BASE_API: '/ekubo', }, HAIKO: { - BASE_APR_API: 'haiko/markets?network=mainnet', + BASE_APR_API: '/haiko/markets?network=mainnet', }, STRKFarm: { BASE_APR_API: '/api/strategies', From 96ef905506e13c30dc81000bcf3d780d689e99b1 Mon Sep 17 00:00:00 2001 From: akiraonstarknet Date: Tue, 12 Nov 2024 20:15:18 +0700 Subject: [PATCH 08/22] update eth xl address --- src/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants.ts b/src/constants.ts index 3b7e589..049567d 100755 --- a/src/constants.ts +++ b/src/constants.ts @@ -63,7 +63,7 @@ const CONSTANTS = { DeltaNeutralMMETHUSDC: '0x9d23d9b1fa0db8c9d75a1df924c3820e594fc4ab1475695889286f3f6df250', DeltaNeutralMMETHUSDCXL: - '0x5852a2fa5f3fa08fc8b0b95096792a954009da28e1fa08430bde9e91bf395fe', + '0x9140757f8fb5748379be582be39d6daf704cc3a0408882c0d57981a885eed9', }, MOBILE_MSG: 'Desktop/Tablet only', }; From 73919e344633a7df3ef634db4109ce5402c63c7e Mon Sep 17 00:00:00 2001 From: akiraonstarknet Date: Tue, 12 Nov 2024 23:55:05 +0700 Subject: [PATCH 09/22] update audit info on XL pool --- src/components/Navbar.tsx | 4 ++-- src/store/protocols.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 0071425..fe7bcc5 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -213,7 +213,7 @@ export default function Navbar(props: NavbarProps) { top="0" > -
+ {/*
-
+
*/} Date: Wed, 20 Nov 2024 20:57:28 +0700 Subject: [PATCH 10/22] fix mobile wallet issue --- src/components/Navbar.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index fe7bcc5..c486530 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -55,14 +55,15 @@ import { } from 'starknetkit/argentMobile'; import { WebWalletConnector } from 'starknetkit/webwallet'; import TncModal from './TncModal'; +import { constants } from 'starknet'; export const MYCONNECTORS: any[] = isInArgentMobileAppBrowser() ? [ ArgentMobileConnector.init({ options: { dappName: 'STRKFarm', - projectId: 'strkfarm', - url: 'https://app.strkfarm.xyz', + url: window.location.hostname, + chainId: constants.NetworkName.SN_MAIN, }, inAppBrowserOptions: {}, }), @@ -74,8 +75,8 @@ export const MYCONNECTORS: any[] = isInArgentMobileAppBrowser() ArgentMobileConnector.init({ options: { dappName: 'STRKFarm', - projectId: 'strkfarm', - url: 'https://app.strkfarm.xyz', + url: window.location.hostname, + chainId: constants.NetworkName.SN_MAIN, }, }), ]; From 765513f861e690e1aa0c3527db6b1eaea4a8616b Mon Sep 17 00:00:00 2001 From: akiraonstarknet Date: Wed, 20 Nov 2024 21:05:30 +0700 Subject: [PATCH 11/22] fix mobile wallet issue [2] --- src/components/Navbar.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index c486530..9a261ab 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -31,6 +31,7 @@ import { getERC20Balance } from '@/store/balance.atoms'; import { addressAtom } from '@/store/claims.atoms'; import { lastWalletAtom } from '@/store/utils.atoms'; import { + getEndpoint, getTokenInfoFromName, MyMenuItemProps, MyMenuListProps, @@ -62,7 +63,7 @@ export const MYCONNECTORS: any[] = isInArgentMobileAppBrowser() ArgentMobileConnector.init({ options: { dappName: 'STRKFarm', - url: window.location.hostname, + url: getEndpoint(), chainId: constants.NetworkName.SN_MAIN, }, inAppBrowserOptions: {}, @@ -75,7 +76,7 @@ export const MYCONNECTORS: any[] = isInArgentMobileAppBrowser() ArgentMobileConnector.init({ options: { dappName: 'STRKFarm', - url: window.location.hostname, + url: getEndpoint(), chainId: constants.NetworkName.SN_MAIN, }, }), From 1922eb3abff69677063fb0ed5994f30f4bae3963 Mon Sep 17 00:00:00 2001 From: akiraonstarknet Date: Thu, 21 Nov 2024 15:50:48 +0530 Subject: [PATCH 12/22] fix mobile connect issues --- src/app/api/tnc/signUser/route.ts | 112 +++++++++++++----------------- src/components/TncModal.tsx | 81 ++++++++++++++------- src/components/YieldCard.tsx | 3 +- src/store/strkfarm.atoms.ts | 2 +- 4 files changed, 106 insertions(+), 92 deletions(-) diff --git a/src/app/api/tnc/signUser/route.ts b/src/app/api/tnc/signUser/route.ts index dd777d3..c127aca 100644 --- a/src/app/api/tnc/signUser/route.ts +++ b/src/app/api/tnc/signUser/route.ts @@ -9,16 +9,9 @@ import Mixpanel from 'mixpanel'; const mixpanel = Mixpanel.init('118f29da6a372f0ccb6f541079cad56b'); export async function POST(req: Request) { - const { address, signature, _signature } = await req.json(); - - console.debug( - 'address', - address, - 'signature', - signature, - '_signature', - _signature, - ); + const { address, signature } = await req.json(); + + console.debug('address', address, 'signature', signature); if (!address || !signature) { return NextResponse.json({ success: false, @@ -57,64 +50,64 @@ export async function POST(req: Request) { console.debug(`Verifying signature for address: ${parsedAddress}`); console.debug(`SIGNING_DATA`, SIGNING_DATA); const hash = await myAccount.hashMessage(SIGNING_DATA); - try { - // await debug(); - isValid = await verifyMessageHash(myAccount, hash, parsedSignature); - console.debug('isValid', isValid); - mixpanel.track('TnC signed', { - address, - signature, - _signature, - step: 1, - hash, - }); - } catch (error) { - console.error('verification failed [1]:', error); - if (_signature) { + console.debug('hash', hash); + + const function_sigs = ['is_valid_signature', 'isValidSignature']; + const signatures = [ + parsedSignature, + parsedSignature.slice(parsedSignature.length - 2, parsedSignature.length), + ]; + + for (const fn_sig of function_sigs) { + for (const sig of signatures) { try { - const parsedSignature2 = JSON.parse(_signature) as string[]; - isValid = await verifyMessageHash(myAccount, hash, parsedSignature2); + console.log(`Checking: ${fn_sig}`); + console.log(`Signature: ${JSON.stringify(sig)}`); + isValid = await verifyMessageHash(myAccount, hash, sig, fn_sig); console.debug('isValid', isValid); mixpanel.track('TnC signed', { address, signature, - _signature, + step: 1, hash, - step: 2, - }); - } catch (err) { - console.error('verification failed [2]:', err); - - // temporarily accepting all signtures - isValid = true; - mixpanel.track('TnC signing failed', { - address, - signature, - hash, - isValid, - _signature, + fn_sig, }); + break; + } catch (error) { + console.warn(`verification failed [${fn_sig}]:`, error); } } + if (isValid) { + break; + } } - if (!isValid) { - mixpanel.track('TnC signing failed', { - address, - signature, - _signature, - hash, - isValid, - }); - isValid = true; // temporarily accepting all signtures - } + // if (!isValid) { + // mixpanel.track('TnC signing failed', { + // address, + // signature, + // hash, + // isValid, + // }); + // isValid = true; // temporarily accepting all signtures + // } if (!isValid) { - return NextResponse.json({ - success: false, - message: 'Invalid signature. Ensure account is deployed.', - user: null, - }); + try { + const cls = await provider.getClassAt(address, 'pending'); + // means account is deployed + return NextResponse.json({ + success: false, + message: 'Invalid signature. Please contact us if issue persists.', + user: null, + }); + } catch (error) { + return NextResponse.json({ + success: false, + message: 'Invalid signature. Ensure account is deployed.', + user: null, + }); + } } const user = await db.user.findFirst({ @@ -186,18 +179,11 @@ async function verifyMessageHash( }); console.debug('verifyMessageHash resp', resp); if (Number(resp[0]) == 0) { - return false; + throw new Error('Invalid signature'); } return true; } catch (err: any) { console.error('Error verifying signature:', err); - if (entrypoint === 'isValidSignature') { - console.debug( - 'could be Invalid message selector, trying with is_valid_signature', - ); - return verifyMessageHash(account, hash, signature, 'is_valid_signature'); - } - if ( [ 'argent/invalid-signature', diff --git a/src/components/TncModal.tsx b/src/components/TncModal.tsx index ea8c9cb..d585dcc 100644 --- a/src/components/TncModal.tsx +++ b/src/components/TncModal.tsx @@ -13,7 +13,11 @@ import { Text, useDisclosure, } from '@chakra-ui/react'; -import { useAccount, useDisconnect } from '@starknet-react/core'; +import { + useAccount, + useDisconnect, + useSignTypedData, +} from '@starknet-react/core'; import axios from 'axios'; import { atomWithQuery } from 'jotai-tanstack-query'; import React, { useEffect, useMemo, useState } from 'react'; @@ -55,6 +59,14 @@ const TncModal: React.FC = (props) => { const [isSigningPending, setIsSigningPending] = useState(false); const { disconnectAsync } = useDisconnect(); + const { + signTypedData, + error: signingError, + data: sigData, + } = useSignTypedData({ + params: SIGNING_DATA, + }); + // set ref code of the user if it exists useEffect(() => { if (!userTncInfo) return; @@ -97,39 +109,54 @@ const TncModal: React.FC = (props) => { })(); }, [userTncInfo]); - const handleSign = async () => { - if (!address || !account) { + useEffect(() => { + console.log('signature', sigData); + if (signingError) { + toast.error(signingError.message, { + position: 'bottom-right', + }); + setIsSigningPending(false); + } + if (!address || !account || !sigData) { return; } - mixpanel.track('TnC agreed', { address }); - setIsSigningPending(true); + async function processSign() { + try { + if (!sigData) { + return; + } - try { - const _signature = (await account.signMessage(SIGNING_DATA)) as string[]; - - console.log('signature', _signature); - const sig_len = _signature.length; - const signature = - sig_len > 2 ? _signature.slice(sig_len - 2, sig_len) : _signature; - if (signature && signature.length > 0) { - const res2 = await axios.post('/api/tnc/signUser', { - address, - signature: JSON.stringify(signature), - _signature: JSON.stringify(_signature), - }); - - if (res2.data?.success) { - onClose(); - } else { - toast.error(res2.data?.message || 'Error verifying T&C'); + const signature = sigData; + if (signature && signature.length > 0) { + const res2 = await axios.post('/api/tnc/signUser', { + address, + signature: JSON.stringify(signature), + }); + + if (res2.data?.success) { + onClose(); + } else { + toast.error(res2.data?.message || 'Error verifying T&C'); + } } + } catch (error) { + console.error('signature', error); + mixpanel.track('TnC signing failed', { address }); } - } catch (error) { - console.error('signature', error); - mixpanel.track('TnC signing failed', { address }); + setIsSigningPending(false); } - setIsSigningPending(false); + processSign(); + }, [sigData, signingError]); + + const handleSign = async () => { + if (!address || !account) { + return; + } + mixpanel.track('TnC agreed', { address }); + + setIsSigningPending(true); + signTypedData(); }; return ( diff --git a/src/components/YieldCard.tsx b/src/components/YieldCard.tsx index ea10b20..4dfecd8 100644 --- a/src/components/YieldCard.tsx +++ b/src/components/YieldCard.tsx @@ -32,6 +32,7 @@ import { getPoolInfoFromStrategy, sortAtom } from '@/store/protocols'; import { TriangleDownIcon, TriangleUpIcon } from '@chakra-ui/icons'; import mixpanel from 'mixpanel-browser'; import { STRKFarmStrategyAPIResult } from '@/store/strkfarm.atoms'; +import { isMobile } from 'react-device-detect'; interface YieldCardProps { pool: PoolInfo; @@ -468,7 +469,7 @@ function StrategyMobileCard(props: YieldCardProps) { function getLinkProps(pool: PoolInfo, showProtocolName?: boolean) { return { href: pool.protocol.link, - target: '_blank', + target: isMobile ? '_self' : '_blank', onClick: () => { mixpanel.track('Pool clicked', { pool: pool.pool.name, diff --git a/src/store/strkfarm.atoms.ts b/src/store/strkfarm.atoms.ts index 1733dee..b0b0aa5 100644 --- a/src/store/strkfarm.atoms.ts +++ b/src/store/strkfarm.atoms.ts @@ -87,7 +87,7 @@ export class STRKFarm extends IDapp { additional: { riskFactor, tags: [getLiveStatusEnum(rawPool.status.number)], - isAudited: true, + isAudited: poolName.includes('XL') ? false : true, }, }; return poolInfo; From f0d502c657cb99102f666895ee0c96270e220a18 Mon Sep 17 00:00:00 2001 From: akiraonstarknet Date: Thu, 21 Nov 2024 19:36:59 +0530 Subject: [PATCH 13/22] auto connect bug --- src/app/slinks/template.tsx | 5 +- src/app/template.tsx | 5 +- src/components/Navbar.tsx | 180 ++++++++++++++++++------------------ 3 files changed, 95 insertions(+), 95 deletions(-) diff --git a/src/app/slinks/template.tsx b/src/app/slinks/template.tsx index 679d6d2..55454e2 100755 --- a/src/app/slinks/template.tsx +++ b/src/app/slinks/template.tsx @@ -1,6 +1,6 @@ 'use client'; -import Navbar, { MYCONNECTORS } from '@/components/Navbar'; +import Navbar, { getConnectors } from '@/components/Navbar'; import { MY_STORE } from '@/store'; import { Center, @@ -16,6 +16,7 @@ import mixpanel from 'mixpanel-browser'; import Image from 'next/image'; import { usePathname } from 'next/navigation'; import * as React from 'react'; +import { isMobile } from 'react-device-detect'; import { Toaster } from 'react-hot-toast'; import { RpcProviderOptions, constants } from 'starknet'; @@ -96,7 +97,7 @@ export default function Template({ children }: { children: React.ReactNode }) { diff --git a/src/app/template.tsx b/src/app/template.tsx index acd3d80..2b8664d 100755 --- a/src/app/template.tsx +++ b/src/app/template.tsx @@ -1,6 +1,6 @@ 'use client'; -import Navbar, { MYCONNECTORS } from '@/components/Navbar'; +import Navbar, { getConnectors } from '@/components/Navbar'; import { MY_STORE } from '@/store'; import { Center, @@ -20,6 +20,7 @@ import { Toaster } from 'react-hot-toast'; import { RpcProviderOptions, constants } from 'starknet'; import { Inter } from 'next/font/google'; +import { isMobile } from 'react-device-detect'; const inter = Inter({ subsets: ['latin'] }); mixpanel.init('118f29da6a372f0ccb6f541079cad56b'); @@ -108,7 +109,7 @@ export default function Template({ children }: { children: React.ReactNode }) { diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 9a261ab..21969fb 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -22,9 +22,12 @@ import { useDisclosure, } from '@chakra-ui/react'; import { useAtom, useSetAtom } from 'jotai'; -import { useStarknetkitConnectModal } from 'starknetkit'; +import { + connect, + ConnectOptionsWithConnectors, + StarknetkitConnector, +} from 'starknetkit'; -import { CONNECTOR_NAMES } from '@/app/template'; import tg from '@/assets/tg.svg'; import CONSTANTS from '@/constants'; import { getERC20Balance } from '@/store/balance.atoms'; @@ -48,7 +51,7 @@ import { useStarkProfile, } from '@starknet-react/core'; import mixpanel from 'mixpanel-browser'; -import { useEffect } from 'react'; +import { useEffect, useMemo } from 'react'; import { isMobile } from 'react-device-detect'; import { ArgentMobileConnector, @@ -58,29 +61,46 @@ import { WebWalletConnector } from 'starknetkit/webwallet'; import TncModal from './TncModal'; import { constants } from 'starknet'; -export const MYCONNECTORS: any[] = isInArgentMobileAppBrowser() - ? [ - ArgentMobileConnector.init({ - options: { - dappName: 'STRKFarm', - url: getEndpoint(), - chainId: constants.NetworkName.SN_MAIN, - }, - inAppBrowserOptions: {}, - }), - ] - : [ - new InjectedConnector({ options: { id: 'braavos', name: 'Braavos' } }), - new InjectedConnector({ options: { id: 'argentX', name: 'Argent X' } }), - new WebWalletConnector({ url: 'https://web.argent.xyz' }), - ArgentMobileConnector.init({ - options: { - dappName: 'STRKFarm', - url: getEndpoint(), - chainId: constants.NetworkName.SN_MAIN, - }, - }), - ]; +export function getConnectors(isMobile: boolean) { + const mobileConnector = ArgentMobileConnector.init({ + options: { + dappName: 'STRKFarm', + url: getEndpoint(), + chainId: constants.NetworkName.SN_MAIN, + }, + inAppBrowserOptions: {}, + }) as StarknetkitConnector; + + const argentXConnector = new InjectedConnector({ + options: { + id: 'argentX', + name: 'Argent X', + }, + }); + + const braavosConnector = new InjectedConnector({ + options: { + id: 'braavos', + name: 'Braavos', + }, + }); + + const webWalletConnector = new WebWalletConnector({ + url: 'https://web.argent.xyz', + }) as StarknetkitConnector; + + if (isInArgentMobileAppBrowser()) { + return [mobileConnector]; + } else if (isMobile) { + return [braavosConnector, mobileConnector, webWalletConnector]; + } + return [ + argentXConnector, + braavosConnector, + mobileConnector, + webWalletConnector, + ]; +} interface NavbarProps { hideTg?: boolean; @@ -89,29 +109,15 @@ interface NavbarProps { export default function Navbar(props: NavbarProps) { const { address, connector, account } = useAccount(); - const { connect, connectors } = useConnect(); const { disconnectAsync } = useDisconnect(); const setAddress = useSetAtom(addressAtom); const { data: starkProfile } = useStarkProfile({ address, useDefaultPfp: true, }); + const { connect: connectSnReact } = useConnect(); const [lastWallet, setLastWallet] = useAtom(lastWalletAtom); - const { starknetkitConnectModal: starknetkitConnectModal1 } = - useStarknetkitConnectModal({ - modalMode: 'canAsk', - modalTheme: 'dark', - connectors: MYCONNECTORS, - }); - - // backup - const { starknetkitConnectModal: starknetkitConnectModal2 } = - useStarknetkitConnectModal({ - modalMode: 'alwaysAsk', - modalTheme: 'dark', - connectors: MYCONNECTORS, - }); const getTokenBalance = async (token: string, address: string) => { const tokenInfo = getTokenInfoFromName(token); @@ -122,6 +128,41 @@ export default function Navbar(props: NavbarProps) { console.log(account, 'account'); + const connectorConfig: ConnectOptionsWithConnectors = useMemo(() => { + return { + modalMode: 'canAsk', + modalTheme: 'dark', + webWalletUrl: 'https://web.argent.xyz', + argentMobileOptions: { + dappName: 'STRKFarm', + chainId: constants.NetworkName.SN_MAIN, + url: window.location.hostname, + }, + dappName: 'Endur.fi', + connectors: getConnectors(isMobile) as StarknetkitConnector[], + }; + }, [isMobile]); + + async function connectWallet(config = connectorConfig) { + try { + const { connector } = await connect(config); + + if (connector) { + connectSnReact({ connector: connector as any }); + } + } catch (error) { + console.error('connectWallet error', error); + } + } + + useEffect(() => { + const config = connectorConfig; + connectWallet({ + ...config, + modalMode: 'neverAsk', + }); + }, []); + useEffect(() => { (async () => { if (address) { @@ -139,55 +180,6 @@ export default function Navbar(props: NavbarProps) { })(); }, [address]); - // Connect wallet using starknetkit - const connectWallet = async () => { - try { - const result = await starknetkitConnectModal1(); - if (!result.connector) { - throw new Error('No connector found'); - } - - connect({ connector: result.connector }); - } catch (error) { - console.warn('connectWallet error', error); - try { - const result = await starknetkitConnectModal2(); - if (!result.connector) { - throw new Error('No connector found'); - } - connect({ connector: result.connector }); - } catch (error) { - console.error('connectWallet error', error); - alert('Error connecting wallet'); - } - } - }; - - function autoConnect(retry = 0) { - console.log('lastWallet', lastWallet, connectors); - try { - if (!address && lastWallet) { - const connectorIndex = CONNECTOR_NAMES.findIndex( - (name) => name === lastWallet, - ); - if (connectorIndex >= 0) { - connect({ connector: MYCONNECTORS[connectorIndex] }); - } - } - } catch (error) { - console.error('lastWallet error', error); - if (retry < 10) { - setTimeout(() => { - autoConnect(retry + 1); - }, 1000); - } - } - } - // Auto-connects to last wallet - useEffect(() => { - autoConnect(); - }, [lastWallet]); - // Set last wallet when a new wallet is connected useEffect(() => { console.log('lastWallet connector', connector?.name); @@ -402,7 +394,13 @@ export default function Navbar(props: NavbarProps) { my={{ base: 'auto', sm: 'initial' }} paddingX={{ base: '0.5rem', sm: '1rem' }} fontSize={{ base: '0.8rem', sm: '1rem' }} - onClick={address ? undefined : connectWallet} + onClick={ + address + ? undefined + : () => { + connectWallet(); + } + } size="xs" >
From 9d34cc24dfff172b776bdf4c464a7d15baf06b16 Mon Sep 17 00:00:00 2001 From: akiraonstarknet Date: Thu, 21 Nov 2024 19:40:54 +0530 Subject: [PATCH 14/22] fix build issue --- src/components/Navbar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 21969fb..4c27ea2 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -136,7 +136,7 @@ export default function Navbar(props: NavbarProps) { argentMobileOptions: { dappName: 'STRKFarm', chainId: constants.NetworkName.SN_MAIN, - url: window.location.hostname, + url: getEndpoint(), }, dappName: 'Endur.fi', connectors: getConnectors(isMobile) as StarknetkitConnector[], From 5e4c07aaa801b0456feb282e724566249aa4139a Mon Sep 17 00:00:00 2001 From: akiraonstarknet Date: Thu, 21 Nov 2024 19:46:51 +0530 Subject: [PATCH 15/22] remove raffle --- src/components/Navbar.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 4c27ea2..c70c8f5 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -285,7 +285,7 @@ export default function Navbar(props: NavbarProps) { Home - + {/* - + */}