Skip to content

Commit

Permalink
Frontend SDK Integration (#234)
Browse files Browse the repository at this point in the history
- Constants fully moved to the core and frontend uses the core's
constants.
- Safety utils are now used from the core
- useMemecoin hook now uses the useMemecoin hook from the hooks package
- useQuoteToken, useQuoteTokenPrice hooks are imported from the hooks
package
- Deploy, Launch, Collect Fees, Extend Liquidty Lock actions are now
uses the core's Factory methods

closes #227

---------

Co-authored-by: 0xChqrles <clanier.dev@gmail.com>
  • Loading branch information
ugur-eren and 0xChqrles committed May 2, 2024
1 parent 135cec8 commit 0127e7f
Show file tree
Hide file tree
Showing 74 changed files with 619 additions and 3,301 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"g:test": "turbo run test",
"g:test:watch": "turbo run test:watch",
"g:prepare": "turbo run prepare",
"g:rm:local-packages": "rm -rf ./node_modules/core ./node_modules/hooks",
"g:rm:nodemodules": "rm -rf node_modules"
},
"workspaces": [
Expand Down
3 changes: 0 additions & 3 deletions packages/core/src/constants/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ export enum LiquidityType {
EKUBO_NFT = 'EKUBO_NFT',
}

export const STARKNET_POLLING = 3_000 // 3s
export const STARKNET_MAX_BLOCK_TIME = 3600 * 2 // 2h

export const MIN_STARTING_MCAP = 5_000 // $5k
export const RECOMMENDED_STARTING_MCAP = 10_000 // $12k

Expand Down
18 changes: 0 additions & 18 deletions packages/core/src/factory/default.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { constants, RpcProvider } from 'starknet'
import { describe, expect, test } from 'vitest'

import * as TestData from '../../test/TestData'
import { getPairPrice } from '../utils/price'
import { Factory } from './default'

const provider = new RpcProvider({
Expand Down Expand Up @@ -48,23 +47,6 @@ describe('Default Factory', () => {
expect(launchData).toMatchObject(TestData.launched.launchData)
})

test('Starting Market Cap', async () => {
const memecoin = await factory.getMemecoin(TestData.launched.address)

expect(memecoin).toBeDefined()
expect(memecoin?.isLaunched).toBe(true)
if (!memecoin || !memecoin.isLaunched) return

const quoteTokenPrice = await getPairPrice(
factory.config.provider,
memecoin.quoteToken?.usdcPair,
memecoin.launch.blockNumber - 1,
)
const startingMarketCap = factory.getStartingMarketCap(memecoin, quoteTokenPrice)

expect(startingMarketCap?.toFixed(0)).toBe('4972')
})

test('Ekubo Fees', async () => {
const memecoin = await factory.getMemecoin(TestData.launched.address)

Expand Down
39 changes: 3 additions & 36 deletions packages/core/src/factory/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
StandardAMMLaunchData,
} from '../types/memecoin'
import { multiCallContract } from '../utils/contract'
import { getInitialPrice, getStartingTick } from '../utils/ekubo'
import { getStartingTick } from '../utils/ekubo'
import { decimalsScale } from '../utils/helpers'
import { getPairPrice } from '../utils/price'
import { FactoryConfig, FactoryInterface } from './interface'
Expand Down Expand Up @@ -236,39 +236,6 @@ export class Factory implements FactoryInterface {
} satisfies Partial<EkuboLiquidity>
}

//
// GET MCAP
//

public getStartingMarketCap(memecoin: Memecoin, quoteTokenPriceAtLaunch?: Fraction): Fraction | undefined {
if (!memecoin.isLaunched || !quoteTokenPriceAtLaunch || !memecoin.quoteToken) return undefined

switch (memecoin.liquidity.type) {
case LiquidityType.STARKDEFI_ERC20:
case LiquidityType.JEDISWAP_ERC20: {
// starting mcap = quote amount in liq * (team allocation % + 100) * quote token price at launch
return new Fraction(memecoin.liquidity.quoteAmount)
.multiply(new Fraction(memecoin.launch.teamAllocation, memecoin.totalSupply).add(1))
.divide(decimalsScale(memecoin.quoteToken.decimals))
.multiply(quoteTokenPriceAtLaunch)
}

case LiquidityType.EKUBO_NFT: {
// get starting price from starting tick
const initialPrice = getInitialPrice(memecoin.liquidity.startingTick)

// starting mcap = initial price * quote token price at launch * total supply
return new Fraction(
initialPrice.toFixed(DECIMALS).replace(/\./, '').replace(/^0+/, ''), // from 0.000[...]0001 to "1"
decimalsScale(DECIMALS),
)
.multiply(quoteTokenPriceAtLaunch)
.multiply(memecoin.totalSupply)
.divide(decimalsScale(DECIMALS))
}
}
}

//
// GET FEES
//
Expand Down Expand Up @@ -433,7 +400,7 @@ export class Factory implements FactoryInterface {
const launchCalldata = CallData.compile([
memecoin.address, // memecoin address
data.antiBotPeriod, // anti bot period in seconds
data.holdLimit, // hold limit
+data.holdLimit.toFixed(1) * 100, // hold limit
data.quoteToken.address, // quote token address
initialHolders, // initial holders
initialHoldersAmounts, // initial holders amounts
Expand Down Expand Up @@ -494,7 +461,7 @@ export class Factory implements FactoryInterface {
const launchCalldata = CallData.compile([
memecoin.address, // memecoin address
data.antiBotPeriod, // anti bot period in seconds
data.holdLimit, // hold limit
+data.holdLimit.toFixed(1) * 100, // hold limit
data.quoteToken.address, // quote token
initialHolders, // initial holders
initialHoldersAmounts, // intial holders amounts
Expand Down
2 changes: 0 additions & 2 deletions packages/core/src/factory/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ export abstract class FactoryInterface {

public abstract getMemecoinLaunchData(address: string): Promise<LaunchedMemecoin>

public abstract getStartingMarketCap(memecoin: Memecoin, quoteTokenPriceAtLaunch?: Fraction): Fraction | undefined

public abstract getEkuboFees(memecoin: Memecoin): Promise<Fraction | undefined>

public abstract getCollectEkuboFeesCalldata(memecoin: Memecoin): { calls: CallDetails[] } | undefined
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/types/memecoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ type MemecoinBaseLaunchData = {
address: string
amount: number | string
}[]
holdLimit: number
holdLimit: Percent

/**
* Anti bot period in *seconds*
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/types/tokens.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { QUOTE_TOKEN_SYMBOL } from 'src/constants'
import { constants } from 'starknet'

import { QUOTE_TOKEN_SYMBOL } from '../constants'

export type USDCPair = {
address: string
reversed: boolean
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './ekubo'
export * from './marketCap'
export * from './price'
export * from './safety'
30 changes: 30 additions & 0 deletions packages/core/src/utils/marketCap.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { constants, RpcProvider } from 'starknet'
import { expect, test } from 'vitest'

import * as TestData from '../../test/TestData'
import { Factory } from '../factory/default'
import { getStartingMarketCap } from './marketCap'
import { getPairPrice } from './price'

const provider = new RpcProvider({
nodeUrl: 'https://starknet-mainnet.public.blastapi.io',
})

const factory = new Factory({ provider, chainId: constants.StarknetChainId.SN_MAIN })

test('Starting Market Cap', async () => {
const memecoin = await factory.getMemecoin(TestData.launched.address)

expect(memecoin).toBeDefined()
expect(memecoin?.isLaunched).toBe(true)
if (!memecoin || !memecoin.isLaunched) return

const quoteTokenPrice = await getPairPrice(
factory.config.provider,
memecoin.quoteToken?.usdcPair,
memecoin.launch.blockNumber - 1,
)
const startingMarketCap = getStartingMarketCap(memecoin, quoteTokenPrice)

expect(startingMarketCap?.toFixed(0)).toBe('4972')
})
36 changes: 36 additions & 0 deletions packages/core/src/utils/marketCap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Fraction } from '@uniswap/sdk-core'

import { DECIMALS, LiquidityType } from '../constants'
import { Memecoin } from '../types'
import { getInitialPrice } from './ekubo'
import { decimalsScale } from './helpers'

// eslint-disable-next-line import/no-unused-modules
export function getStartingMarketCap(memecoin: Memecoin, quoteTokenPriceAtLaunch?: Fraction): Fraction | undefined {
if (!memecoin.isLaunched || !quoteTokenPriceAtLaunch || !memecoin.quoteToken) return undefined

switch (memecoin.liquidity.type) {
case LiquidityType.STARKDEFI_ERC20:
case LiquidityType.JEDISWAP_ERC20: {
// starting mcap = quote amount in liq * (team allocation % + 100) * quote token price at launch
return new Fraction(memecoin.liquidity.quoteAmount)
.multiply(new Fraction(memecoin.launch.teamAllocation, memecoin.totalSupply).add(1))
.divide(decimalsScale(memecoin.quoteToken.decimals))
.multiply(quoteTokenPriceAtLaunch)
}

case LiquidityType.EKUBO_NFT: {
// get starting price from starting tick
const initialPrice = getInitialPrice(memecoin.liquidity.startingTick)

// starting mcap = initial price * quote token price at launch * total supply
return new Fraction(
initialPrice.toFixed(DECIMALS).replace(/\./, '').replace(/^0+/, ''), // from 0.000[...]0001 to "1"
decimalsScale(DECIMALS),
)
.multiply(quoteTokenPriceAtLaunch)
.multiply(memecoin.totalSupply)
.divide(decimalsScale(DECIMALS))
}
}
}
23 changes: 23 additions & 0 deletions packages/core/src/utils/price.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { constants, RpcProvider } from 'starknet'
import { describe, expect, test } from 'vitest'

import { Ether } from '../constants'
import { getPairPrice } from './price'

const provider = new RpcProvider({
nodeUrl: 'https://starknet-mainnet.public.blastapi.io',
})

describe('Price', () => {
test('No pair', async () => {
const price = await getPairPrice(provider)

expect(price.toFixed(0)).toBe('1')
})

test('USDC Pair', async () => {
const price = await getPairPrice(provider, Ether[constants.StarknetChainId.SN_MAIN].usdcPair, 500_000)

expect(price.toFixed(0)).toBe('2309')
})
})
3 changes: 3 additions & 0 deletions packages/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@
"@hookform/resolvers": "^3.3.2",
"@starknet-react/chains": "^0.1.0",
"@starknet-react/core": "^2.2.4",
"@tanstack/react-query": "^5.0.1",
"@types/react-dom": "^18.2.1",
"@uniswap/sdk-core": "^4.0.9",
"@vanilla-extract/css": "^1.11.0",
"@vanilla-extract/recipes": "^0.4.0",
"@vanilla-extract/sprinkles": "^1.6.0",
"clsx": "^2.0.0",
"core": "*",
"eslint": "^8.0.0",
"hooks": "*",
"lucide-react": "^0.294.0",
"moment": "^2.30.1",
"ms.macro": "^2.0.0",
Expand Down
Loading

0 comments on commit 0127e7f

Please sign in to comment.