[no-impact] ts-prune (re-merge) (#1623)

Co-authored-by: Adrian Brzeziński <a.brzezinski94@gmail.com>
This commit is contained in:
agrippa 2023-05-14 18:08:36 -04:00 committed by GitHub
parent dab3d44b44
commit d56625557b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
87 changed files with 97 additions and 3768 deletions

View File

@ -1,13 +1,6 @@
import { EndpointTypes } from '@models/types'
import type { AccountInfo, PublicKey } from '@solana/web3.js'
export interface EndpointInfo {
name: EndpointTypes
url: string
}
export interface TokenAccount {
pubkey: PublicKey
account: AccountInfo<Buffer> | null
effectiveMint: PublicKey
}

View File

@ -26,7 +26,7 @@ export const getGatekeeperNetwork = async (
return registrarObject.gatekeeperNetwork
}
export const getPredecessorProgramId = async (
const getPredecessorProgramId = async (
client: GatewayClient,
realm: ProgramAccount<Realm>
): Promise<PublicKey | null> => {

View File

@ -7,7 +7,7 @@ import { SubDaoWithMeta } from 'HeliumVotePlugin/sdk/types'
import { useSubDaos } from 'HeliumVotePlugin/hooks/useSubDaos'
import { LoadingDots } from '@components/Loading'
export interface DelegateTokensModalProps {
interface DelegateTokensModalProps {
isOpen: boolean
onClose: () => void
onSubmit: (subDao: SubDaoWithMeta) => Promise<void>

View File

@ -37,7 +37,7 @@ import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
import { PublicKey } from '@solana/web3.js'
import { PromptModal } from './PromptModal'
export interface PositionCardProps {
interface PositionCardProps {
subDaos?: SubDaoWithMeta[]
position: PositionWithMeta
tokenOwnerRecordPk: PublicKey | null

View File

@ -3,7 +3,7 @@ import Modal from '@components/Modal'
import Button, { SecondaryButton } from '@components/Button'
import { notify } from '@utils/notifications'
export interface PromptModalProps {
interface PromptModalProps {
isOpen: boolean
title?: string
message: string

View File

@ -12,7 +12,7 @@ import Input from '@components/inputs/Input'
import { useSolanaUnixNow } from '@hooks/useSolanaUnixNow'
import { BN } from '@coral-xyz/anchor'
export interface TransferTokensModalProps {
interface TransferTokensModalProps {
isOpen: boolean
positions: PositionWithMeta[]
maxTransferAmount: number

View File

@ -6,7 +6,7 @@ import { getMintDecimalAmount } from '@tools/sdk/units'
import { LightningBoltIcon } from '@heroicons/react/solid'
import Tooltip from '@components/Tooltip'
export interface VotingPowerBoxProps {
interface VotingPowerBoxProps {
votingPower: BN
mint: MintInfo
votingPowerFromDeposits: BN

View File

@ -29,8 +29,8 @@ export interface PositionWithMeta extends Position {
}
}
export type LockupKind = IdlTypes<HeliumVoterStakeRegistry>['LockupKind']
export type InitializePositionV0Args = IdlTypes<HeliumVoterStakeRegistry>['InitializePositionArgsV0']
/* export type InitializePositionV0Args = IdlTypes<HeliumVoterStakeRegistry>['InitializePositionArgsV0']
*/
export type SubDao = IdlAccounts<HeliumSubDaos>['subDaoV0']
export interface SubDaoWithMeta extends Omit<SubDao, 'dntMint'> {
pubkey: PublicKey

View File

@ -9,7 +9,6 @@ import { BN } from '@coral-xyz/anchor'
import { AssetAccount } from '@utils/uiTypes/assets'
import { ConnectionContext } from '@utils/connection'
import { VotingClient } from '@utils/uiTypes/VotePlugin'
import numbro from 'numbro'
import tokenPriceService from '@utils/services/tokenPrice'
import { Pool } from '@everlend/general-pool'
import axios from 'axios'
@ -164,18 +163,3 @@ export const calcUserTokenBalanceByPoolToken = (
: Math.round(tokenBalanceByDecimalMultiplier)) / decimalMultiplier
)
}
export const convertToCurrency = (
amount: number,
rate: number,
mantissa?: number
): number => {
if (mantissa) {
return Number(
numbro(amount * rate).format({
mantissa,
})
)
}
return amount * rate
}

View File

@ -1,12 +1,4 @@
import {
ProgramAccount,
Realm,
RpcContext,
TokenOwnerRecord,
} from '@solana/spl-governance'
import { PublicKey, TransactionInstruction } from '@solana/web3.js'
import { VotingClient } from '@utils/uiTypes/VotePlugin'
import { AssetAccount } from '@utils/uiTypes/assets'
import { PublicKey } from '@solana/web3.js'
import {
CreateSolendStrategyParams,
SolendSubStrategy,
@ -34,12 +26,12 @@ export interface TreasuryStrategy {
/** When true, does not display protocol or name */
noProtocol?: boolean
}
/*
export type MangoStrategy = TreasuryStrategy & {
//async function that pass all props needed to create proposal
// if promise is successfully resolved it will automatically redirect to created proposal
createProposalFcn: HandleCreateProposalWithStrategy
}
} */
export type SolendStrategy = TreasuryStrategy & {
reserves: Array<SolendSubStrategy>
@ -62,7 +54,8 @@ export type EverlendStrategy = TreasuryStrategy & {
rateEToken: number
}
export type HandleCreateProposalWithStrategy = (
/*
type HandleCreateProposalWithStrategy = (
{ connection, wallet, programId, programVersion, walletPubkey }: RpcContext,
handledMint: string,
form: MNGODepositForm,
@ -74,14 +67,9 @@ export type HandleCreateProposalWithStrategy = (
prerequisiteInstructions: TransactionInstruction[],
isDraft: boolean,
client?: VotingClient
) => Promise<PublicKey>
export interface NameVal {
name: string
val: string | null
}
export type MNGODepositForm = {
) => Promise<PublicKey> */
/*
type MNGODepositForm = {
mintAmount: number
delegateDeposit: boolean
delegateAddress: string
@ -90,3 +78,4 @@ export type MNGODepositForm = {
description: string
proposalCount: number
}
*/

View File

@ -18,10 +18,10 @@ export const SWITCHBOARD_GRANT_AUTHORITY = new PublicKey(
export const SWITCHBOARD_REVOKE_AUTHORITY = new PublicKey(
'9rkK8T8wnYXZ1SSC6g2ZhbnyL5K5v546XSbNJv7og87b'
)
export const QUEUE_LIST: PublicKey[] = [
/*
const QUEUE_LIST: PublicKey[] = [
new PublicKey('7QN4mJo9U58XMeHEyfY6ckKxAkVLkqVtcWjwgNU6xaE'),
]
] */
export class SwitchboardQueueVoterClient {
constructor(public program: Program<Switchboard>, public devnet?: boolean) {}

View File

@ -1,64 +0,0 @@
import { PublicKey } from '@solana/web3.js'
export const unusedMintPk = '11111111111111111111111111111111'
export const getNftRegistrarPDA = async (
realmPk: PublicKey,
mint: PublicKey,
clientProgramId: PublicKey
) => {
const [registrar, registrarBump] = await PublicKey.findProgramAddress(
[Buffer.from('registrar'), realmPk.toBuffer(), mint.toBuffer()],
clientProgramId
)
return {
registrar,
registrarBump,
}
}
export const getNftMaxVoterWeightRecord = async (
realmPk: PublicKey,
mint: PublicKey,
clientProgramId: PublicKey
) => {
const [
maxVoterWeightRecord,
maxVoterWeightRecordBump,
] = await PublicKey.findProgramAddress(
[
Buffer.from('max-voter-weight-record'),
realmPk.toBuffer(),
mint.toBuffer(),
],
clientProgramId
)
return {
maxVoterWeightRecord,
maxVoterWeightRecordBump,
}
}
export const getNftVoterWeightRecord = async (
realmPk: PublicKey,
mint: PublicKey,
walletPk: PublicKey,
clientProgramId: PublicKey
) => {
const [
voterWeightPk,
voterWeightRecordBump,
] = await PublicKey.findProgramAddress(
[
Buffer.from('voter-weight-record'),
realmPk.toBuffer(),
mint.toBuffer(),
walletPk.toBuffer(),
],
clientProgramId
)
return {
voterWeightPk,
voterWeightRecordBump,
}
}

View File

@ -1,84 +0,0 @@
import { AddressImage, DisplayAddress } from '@cardinal/namespaces-components'
import { UserCircleIcon } from '@heroicons/react/outline'
import useRealm from '@hooks/useRealm'
import { PublicKey } from '@solana/web3.js'
import { getMintDecimalAmount } from '@tools/sdk/units'
import { useMemo } from 'react'
import useWalletStore from 'stores/useWalletStore'
import { LockupType } from 'VoteStakeRegistry/sdk/accounts'
import { getMinDurationFmt, getTimeLeftFromNowFmt } from '@utils/dateTools'
import { DepositWithWallet } from './tools'
const LockTokenRow = ({
depositWithWallet,
index,
}: {
depositWithWallet: DepositWithWallet
index: number
}) => {
const connection = useWalletStore((s) => s.connection)
const { mint } = useRealm()
const fmtMangoAmount = (val) => {
return mint ? getMintDecimalAmount(mint!, val).toFormat(0) : '0'
}
const depositWalletPk = depositWithWallet.wallet
const renderAddressName = useMemo(() => {
return (
<DisplayAddress
connection={connection.current}
address={new PublicKey(depositWalletPk)}
height="12px"
width="100px"
dark={true}
/>
)
}, [depositWalletPk, connection])
const renderAddressImage = useMemo(
() => (
<AddressImage
dark={true}
connection={connection.current}
address={new PublicKey(depositWalletPk)}
height="25px"
width="25px"
placeholder={<UserCircleIcon className="h-6 text-fgd-3 w-6" />}
/>
),
[depositWalletPk, connection]
)
const type = Object.keys(
depositWithWallet.deposit.lockup.kind
)[0] as LockupType
const typeName = type !== 'monthly' ? type : 'Vested'
const isConstant = type === 'constant'
const lockedTokens = fmtMangoAmount(
depositWithWallet.deposit.amountDepositedNative
)
return (
<div
className={`grid grid-cols-4 py-2 px-2 ${
index % 2 === 0 ? 'bg-bkg-3' : ''
} rounded`}
style={{ maxHeight: '40px' }}
>
<div className="underline hover:cursor-pointer flex">
<span className="mr-2">{renderAddressImage}</span> {renderAddressName}
</div>
<div>{typeName}</div>
<div>
{isConstant
? getMinDurationFmt(
depositWithWallet.deposit.lockup.startTs,
depositWithWallet.deposit.lockup.endTs
)
: getTimeLeftFromNowFmt(depositWithWallet.deposit.lockup.endTs)}
</div>
<div>{lockedTokens}</div>
</div>
)
}
export default LockTokenRow

View File

@ -10,7 +10,7 @@ export interface Voter {
//there are more fields but no use for them on ui yet
}
export interface VotingMint {
interface VotingMint {
baselineVoteWeightScaledFactor: BN
digitShift: number
grantAuthority: PublicKey
@ -36,7 +36,7 @@ interface LockupKind {
constant: object
}
export interface Lockup {
interface Lockup {
endTs: BN
kind: LockupKind
startTs: BN

View File

@ -26,7 +26,7 @@ import {
import { trySentryLog } from '@utils/logs'
import { NftVoterClient } from '@utils/uiTypes/NftVoterClient'
export type NFTRealm = Web3Context &
type NFTRealm = Web3Context &
RealmCreation & {
collectionAddress: string
nftCollectionCount: number

View File

@ -12,7 +12,7 @@ import {
} from '@tools/governance/prepareRealmCreation'
import { trySentryLog } from '@utils/logs'
export type TokenizedRealm = Web3Context & RealmCreation
type TokenizedRealm = Web3Context & RealmCreation
export default async function createTokenizedRealm({
connection,

View File

@ -4,13 +4,9 @@ import {
VoteTipping,
} from '@solana/spl-governance'
import { DISABLED_VOTER_WEIGHT } from '@tools/constants'
import { isDisabledVoterWeight } from '@tools/governance/units'
import {
getTimestampFromDays,
getDaysFromTimestamp,
parseMintNaturalAmountFromDecimalAsBN,
fmtBnMintDecimalsUndelimited,
getHoursFromTimestamp,
getTimestampFromHours,
} from '@tools/sdk/units'
@ -44,39 +40,6 @@ type Transformer<T extends Record<keyof U, any>, U> = {
[K in keyof U]: (x: T[K]) => U[K]
}
// @agrippa I use this functional pattern instead of referencing values directly when transforming, so as to reduce surface area for typos
export const transformerGovernanceConfig_2_BaseGovernanceFormFieldsV3 = (
communityMintDecimals: number,
councilMintDecimals: number
): Transformer<
GovernanceConfig & { _programVersion: 3 },
BaseGovernanceFormFieldsV3
> => ({
minInstructionHoldUpTime: (x) => getDaysFromTimestamp(x).toString(),
baseVotingTime: (x) => getDaysFromTimestamp(x).toString(),
minCommunityTokensToCreateProposal: (x) =>
isDisabledVoterWeight(x)
? 'disabled'
: fmtBnMintDecimalsUndelimited(x, communityMintDecimals),
minCouncilTokensToCreateProposal: (x) =>
isDisabledVoterWeight(x)
? 'disabled'
: fmtBnMintDecimalsUndelimited(x, councilMintDecimals),
communityVoteThreshold: (x) =>
x.type === VoteThresholdType.Disabled ? 'disabled' : x.value!.toString(),
communityVetoVoteThreshold: (x) =>
x.type === VoteThresholdType.Disabled ? 'disabled' : x.value!.toString(),
councilVoteThreshold: (x) =>
x.type === VoteThresholdType.Disabled ? 'disabled' : x.value!.toString(),
councilVetoVoteThreshold: (x) =>
x.type === VoteThresholdType.Disabled ? 'disabled' : x.value!.toString(),
communityVoteTipping: (x) => x,
councilVoteTipping: (x) => x,
votingCoolOffTime: (x) => getHoursFromTimestamp(x).toString(),
depositExemptProposalCount: (x) => x.toString(),
_programVersion: (x) => x,
})
export const transformerBaseGovernanceFormFieldsV3_2_GovernanceConfig = (
communityMintDecimals: number,
councilMintDecimals: number
@ -132,9 +95,3 @@ export const transform = <T extends Record<keyof U, any>, U>(
}
return [obj, errs] as [U, FormErrors<U>]
}
export type BaseGovernanceFormErrorsV3 = FormErrors<
Omit<GovernanceConfig, 'reserved'>
> & {
_programVersion: 3
}

View File

@ -1,102 +0,0 @@
import React from 'react'
import { Menu, Transition } from '@headlessui/react'
import { ChevronDownIcon } from '@heroicons/react/solid'
import { InformationCircleIcon } from '@heroicons/react/outline'
import Loading from '@components/Loading'
import Tooltip from './Tooltip'
interface DropdownOption {
label: string
disabled?: boolean
disabledTooltip?: string
onClick: () => Promise<void>
}
interface DropdownBtnProps {
className: string
label?: string
options: DropdownOption[]
isLoading?: boolean
disabled?: boolean
}
const DropdownBtn: React.FC<DropdownBtnProps> = ({
className,
label = 'Options',
options,
isLoading = false,
disabled = false,
}) => {
const basicClasses = `inline-flex rounded-full w-full justify-center bg-primary-light text-bkg-2 px-4 py-3 text-sm font-medium`
const hoverClasses = `hover:bg-opacity-30 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 hover:bg-fgd-1`
const disabledClasses = disabled
? `!bg-fgd-4 !cursor-not-allowed !text-fgd-3`
: ''
const btnClasses = `${basicClasses} ${hoverClasses} ${disabledClasses}`
return (
<Menu as="div" className={`${className} relative inline-block text-left`}>
{({ open }) => (
<>
<Menu.Button className={`${btnClasses}`}>
{isLoading ? (
<Loading />
) : (
<>
<div className="font-bold">{label}</div>
<ChevronDownIcon
className="ml-2 -mr-1 h-5 w-5"
aria-hidden="true"
/>
</>
)}
</Menu.Button>
<Transition
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
{!disabled && open && (
<Menu.Items
className="absolute right-0 mt-2 w-full origin-top-right divide-y divide-gray-100 rounded-md bg-bkg-3 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
static
>
<div className="px-1 py-1 ">
{options.map((option, idx) => (
<Menu.Item key={`option-${idx}`} disabled={option.disabled}>
{({ active, disabled }) => (
<button
onClick={option.onClick}
className={`${
active
? 'bg-primary-light text-fgd-1'
: 'text-fgd-2'
}
${
disabled ? `cursor-not-allowed !text-fgd-4` : ''
} group flex w-full items-center justify-between rounded-md px-2 py-2 text-sm`}
>
{option.label}
{disabled && option.disabledTooltip && (
<Tooltip content={option.disabledTooltip}>
<InformationCircleIcon className="h-5" />
</Tooltip>
)}
</button>
)}
</Menu.Item>
))}
</div>
</Menu.Items>
)}
</Transition>
</>
)}
</Menu>
)
}
export default DropdownBtn

View File

@ -1,4 +1,4 @@
export type ImageTextElement<T> = {
type ImageTextElement<T> = {
id: T
name: string
image?: string

View File

@ -1,53 +0,0 @@
import { FunctionComponent } from 'react'
import styled from '@emotion/styled'
import tw from 'twin.macro'
const StyledButton = styled.a`
font-weight: 700;
cursor: pointer;
:hover {
${tw`underline`}
}
:disabled {
${tw`cursor-not-allowed opacity-60`}
}
`
// default heroicon does not allow customizing stroke
const ChevronRightIcon = ({ className }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
className={className}
>
<path strokeLinecap="round" strokeLinejoin="round" d="M9 5l7 7-7 7"></path>
</svg>
)
interface LinkProps {
className?: string
}
const Link: FunctionComponent<LinkProps> = ({
children,
className,
...props
}) => {
return (
<StyledButton
className={`${className} pr-5 flex z-10 py-2 text-fgd-1 relative rounded-full`}
{...props}
>
{children}
<ChevronRightIcon
className={`relative stroke-3 top-1 h-4 w-4 text-fgd-1 ml-1`}
/>
</StyledButton>
)
}
export default Link

View File

@ -1,54 +0,0 @@
import { FunctionComponent } from 'react'
import styled from '@emotion/styled'
import tw from 'twin.macro'
const StyledButton = styled.a`
font-weight: 700;
cursor: pointer;
:hover {
${tw`underline`}
}
:disabled {
${tw`cursor-not-allowed opacity-60`}
}
`
// default heroicon does not allow customizing stroke
const ChevronRightIcon = ({ className }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
className={className}
>
<path strokeLinecap="round" strokeLinejoin="round" d="M9 5l7 7-7 7"></path>
</svg>
)
interface LinkLeftProps {
className?: string
href?: string
}
const LinkLeft: FunctionComponent<LinkLeftProps> = ({
children,
className,
...props
}) => {
return (
<StyledButton
className={`${className} flex z-10 text-mango-yellow relative rounded-full`}
{...props}
>
{children}
<ChevronRightIcon
className={`relative stroke-2 top-1 h-4 w-4 text-fgd-1 ml-1`}
/>
</StyledButton>
)
}
export default LinkLeft

View File

@ -1,35 +0,0 @@
import {
CloudDownloadIcon,
DocumentIcon,
LinkIcon,
} from '@heroicons/react/outline'
const LinksCompactWrapper = () => {
return (
<>
<div className="flex justify-center items-center gap-x-3 mt-16 mb-6 pb-6 border-b border-gray-900">
<CloudDownloadIcon className="w-8 text-primary-light" />
<h2>Docs that may help you</h2>
</div>
<a href="https://docs.realms.today/" rel="noreferrer" target="_blank">
<div className="bg-bkg-2 w-full p-4 rounded-md flex items-center justify-start gap-x-3">
<LinkIcon className="w-8 text-primary-light" />
<p>Docs & tutorials</p>
</div>
</a>
<a href="https://spl.solana.com/" rel="noreferrer" target="_blank">
<div className="bg-bkg-2 mt-4 w-full p-4 rounded-md flex items-center justify-start gap-x-3">
<DocumentIcon className="mr-1 w-8 text-primary-light" />
<p>About SPL</p>
</div>
</a>
</>
)
}
export default LinksCompactWrapper

View File

@ -1,59 +0,0 @@
import Link from 'next/link'
export default function RealmsLogo() {
return (
<Link href="/" passHref>
<a>
<svg
className="h-8"
viewBox="0 0 384 128"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M182.312 84.568C177.632 84.568 173.6 81.616 167.768 70.888L166.256 68.08C174.968 67.576 180.08 61.96 180.08 54.112C180.08 45.256 174.032 40 163.592 40H143V90.04H149.12V68.152H159.416L162.368 73.552C169.208 86.512 173.96 90.184 182.096 90.184C182.672 90.184 183.176 90.112 183.68 90.04V84.352C183.32 84.496 182.888 84.568 182.312 84.568ZM163.592 45.4C170.432 45.4 173.744 48.496 173.744 54.112C173.744 59.584 170.504 62.752 163.592 62.752H149.12V45.4H163.592Z"
fill="white"
/>
<path
d="M217.874 78.088C215.498 82.84 212.258 85.72 206.714 85.72C199.874 85.72 195.698 81.256 195.338 74.128H222.05C222.122 73.696 222.122 72.832 222.122 72.184C222.122 61.672 216.074 54.616 206.138 54.616C196.346 54.616 189.074 62.032 189.074 72.76C189.074 83.416 196.562 90.904 206.714 90.904C214.922 90.904 219.746 86.368 222.482 80.968L217.874 78.088ZM206.066 59.728C212.114 59.728 215.426 63.112 215.93 69.304H195.482C196.274 63.328 200.306 59.728 206.066 59.728Z"
fill="white"
/>
<path
d="M243.916 90.904C247.948 90.904 251.836 89.032 254.356 85.576V90.04H260.332V68.368C260.332 59.44 254.572 54.616 246.292 54.616C238.372 54.616 232.684 59.152 230.884 66.496L236.284 68.008C237.58 62.608 240.604 59.8 246.22 59.8C251.332 59.8 254.356 63.112 254.356 68.584V73.12C252.124 71.032 248.596 69.016 243.916 69.016C236.212 69.016 230.668 73.912 230.668 79.96C230.668 86.728 236.212 90.904 243.916 90.904ZM244.492 85.936C239.956 85.936 237.004 83.488 237.004 79.96C237.004 76.504 239.956 74.056 244.492 74.056C248.668 74.056 252.196 76.36 254.356 78.88V80.176C252.052 83.488 248.668 85.936 244.492 85.936Z"
fill="white"
/>
<path d="M278.563 90.04V40H272.587V90.04H278.563Z" fill="white" />
<path
d="M331.505 54.616C326.393 54.616 321.929 56.272 318.905 60.808C316.961 56.56 313.001 54.616 307.889 54.616C303.281 54.616 299.393 56.488 297.017 59.8V55.48H291.041V90.04H297.017V69.16C297.017 63.112 301.193 59.8 306.521 59.8C311.849 59.8 314.657 63.112 314.657 69.232V90.04H320.633V69.232C320.633 63.112 324.809 59.8 330.137 59.8C335.465 59.8 338.345 63.112 338.345 69.232V90.04H344.321V68.656C344.321 60.016 339.713 54.616 331.505 54.616Z"
fill="white"
/>
<path
d="M369.637 90.904C377.557 90.904 383.533 87.16 383.533 80.32C383.533 73.192 378.061 71.32 372.301 70.312L368.197 69.592C363.373 68.8 361.573 67.576 361.573 64.48C361.573 61.384 364.381 59.584 369.133 59.584C374.677 59.584 377.197 62.752 377.917 66.064L383.317 64.624C382.309 58.936 377.845 54.616 369.349 54.616C360.925 54.616 355.741 58.504 355.741 64.552C355.741 71.968 361.357 73.84 367.261 74.92L371.293 75.568C375.685 76.36 377.341 77.44 377.341 80.392C377.341 84.136 374.101 85.936 369.781 85.936C364.309 85.936 360.133 83.848 359.557 77.656L354.013 78.664C354.157 87.088 361.357 90.904 369.637 90.904Z"
fill="white"
/>
<path
d="M86.6635 112.55C86.0818 112.773 85.614 112.062 86.0261 111.594C97.213 98.9058 104 82.2452 104 63.9994C104 45.7537 97.213 29.093 86.0261 16.4043C85.6139 15.9369 86.0818 15.2254 86.6635 15.4492C106.162 22.9497 120 41.8586 120 63.9994C120 86.1403 106.162 105.049 86.6635 112.55Z"
fill="#00C2FF"
/>
<path
d="M90.9556 33.4341C91.2154 34.0248 90.391 34.6184 89.8695 34.2384C87.4392 32.4682 83.131 30 78 30C68 30 54 42 54 64C54 86 64 98 76 98C82.4634 98 87.2558 95.4935 89.8371 93.7205C90.369 93.3552 91.2154 93.9753 90.9556 94.5659C84.4901 109.266 71.2627 120 56 120C31.6995 120 8 94.9279 8 64C8 33.0721 31.6995 8 56 8C71.2627 8 84.4901 18.734 90.9556 33.4341Z"
fill="url(#paint0_radial_4624_72632)"
/>
<defs>
<radialGradient
id="paint0_radial_4624_72632"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(76 64) rotate(180) scale(60.4267 80.569)"
>
<stop offset="0.156146" stopColor="#006585" />
<stop offset="1" stopColor="#00C2FF" />
</radialGradient>
</defs>
</svg>
</a>
</Link>
)
}

View File

@ -14,7 +14,7 @@ import { DEFAULT_GOVERNANCE_PROGRAM_ID } from '@components/instructions/tools'
import { PublicKey } from '@solana/web3.js'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
export const Section = ({ children }) => {
const Section = ({ children }) => {
return (
<div className="w-full mx-auto lg:w-5/6 max-w-[770px] px-0 pb-[130px] sm:pb-[250px] relative min-h-[calc(100vh_-_75px)]">
{children}

View File

@ -106,7 +106,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
export default Input
export function FieldMessage({
function FieldMessage({
error = '',
warning = '',
success = '',

View File

@ -31,7 +31,7 @@ export function GenericTokenIcon() {
)
}
export function TokenInfoCell({ title = '', children }) {
function TokenInfoCell({ title = '', children }) {
return (
<div className="flex flex-col h-full px-5 pt-2 pb-3 space-y-1 rounded-md md:space-y-2 md:pt-5 md:pb-5 md:px-6 bg-bkg-2">
<Text level="2" className="text-fgd-2">

View File

@ -116,7 +116,7 @@ export interface AddNFTCollection {
numberOfNFTs: number
}
export interface NFT_Creator {
interface NFT_Creator {
address: string
verified: number
share: number
@ -127,7 +127,7 @@ interface NFT_Attributes {
trait_type: string
value: number
}
export interface NFT {
interface NFT {
name: string
symbol: string
uri: string

View File

@ -1,5 +1,4 @@
/* eslint-disable sort-keys */
export type CountryMetadata = {
type CountryMetadata = {
name: string
dialCode: string
flag: string

View File

@ -15,13 +15,3 @@ export const splitPhoneNumber = (phoneNumber: string): PhoneData => {
return { baseNumber, countryCode }
}
export const formatPhoneNumber = (phoneNumber: string) => {
if (!phoneNumber) {
throw new Error('No phone data found!')
}
return parsePhoneNumber(phoneNumber)
.formatInternational()
.replaceAll(' ', '-')
}

View File

@ -13,7 +13,7 @@ import DialectNotificationsModal from '@components/DialectNotificationsModal'
import NotificationCardContainer from '@components/NotificationsCard/NotificationCardContainer'
import TelegramIcon from './TelegramIcon'
export function useOutsideAlerter(
function useOutsideAlerter(
ref: React.MutableRefObject<Element | null>,
bellRef: React.MutableRefObject<Element | null>,
setOpen: CallableFunction

View File

@ -16,7 +16,7 @@ interface VoteRecords {
[proposal: string]: ProgramAccount<VoteRecord>
}
export function getOwnVoteRecord(
function getOwnVoteRecord(
communityDelegateVoteRecords: VoteRecords,
councilDelegateVoteRecords: VoteRecords,
ownVoteRecords: VoteRecords,

View File

@ -1,36 +0,0 @@
import React, { useEffect, useState } from 'react'
import { ChevronUpIcon } from '@heroicons/react/solid'
export default function ScrollToTop() {
const [isVisible, setIsVisible] = useState(false)
const toggleVisibility = () => {
if (window.pageYOffset > 300) {
setIsVisible(true)
} else {
setIsVisible(false)
}
}
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: 'smooth',
})
}
useEffect(() => {
window.addEventListener('scroll', toggleVisibility)
}, [])
return (
isVisible && (
<div
className="cursor-pointer default-transition fixed bottom-2 lg:bottom-8 right-2 lg:right-8 bg-bkg-4 flex items-center justify-center h-10 rounded-full w-10 hover:bg-fgd-4"
onClick={scrollToTop}
>
<ChevronUpIcon className="h-6 w-6 text-primary-light" />
</div>
)
)
}

View File

@ -23,18 +23,7 @@ import { useEffect, useState } from 'react'
import useGovernanceAssets from '@hooks/useGovernanceAssets'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
export interface TokenMintMetadata {
readonly decimals: number
readonly symbol: string
}
// Mint metadata for Well known tokens displayed on the instruction card
export const MINT_METADATA = {
Gssm3vfi8s65R31SBdmQRq6cKeYojGgup7whkw4VCiQj: { symbol: 'STRM', decimals: 9 },
}
export const STREAMFLOW_PROGRAM_ID =
'strmRqUCoQUgGUan5YhzUZa6KqdzwX5L6FpUxfmKg5m'
const STREAMFLOW_PROGRAM_ID = 'strmRqUCoQUgGUan5YhzUZa6KqdzwX5L6FpUxfmKg5m'
export default function StreamCard({
connection,

View File

@ -1,7 +1,6 @@
import { Disclosure, Transition } from '@headlessui/react'
import { ChevronDownIcon } from '@heroicons/react/solid'
import { Fragment, ReactNode } from 'react'
import dayjs from 'dayjs'
export const Table = ({ children }) => (
<table className="min-w-full">{children}</table>
@ -84,24 +83,3 @@ export const ExpandableRow = ({
</Disclosure>
)
}
type RowProps = {
children: React.ReactNode
}
export const Row = ({ children }: RowProps) => {
return (
<div
className={`default-transition w-full rounded-none border-t border-bkg-4 p-4 font-normal text-fgd-1`}
>
{children}
</div>
)
}
export const TableDateDisplay = ({ date }: { date: string | number }) => (
<>
<p className="mb-0 text-fgd-2">{dayjs(date).format('DD MMM YYYY')}</p>
<p className="mb-0 text-xs">{dayjs(date).format('h:mma')}</p>
</>
)

View File

@ -1,179 +0,0 @@
/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
import Button from '@components/Button'
import Loading from '@components/Loading'
import NFTSelector from '@components/NFTS/NFTSelector'
import useRealm from '@hooks/useRealm'
import { NftVoterClient } from '@utils/uiTypes/NftVoterClient'
import {
getTokenOwnerRecordAddress,
SYSTEM_PROGRAM_ID,
withCreateTokenOwnerRecord,
} from '@solana/spl-governance'
import { Transaction, TransactionInstruction } from '@solana/web3.js'
import { sendTransaction } from '@utils/send'
import useNftPluginStore from 'NftVotePlugin/store/nftPluginStore'
import useVotePluginsClientStore from 'stores/useVotePluginsClientStore'
import useWalletStore from 'stores/useWalletStore'
import { getVoterWeightRecord } from '@utils/plugin/accounts'
import { FC, useEffect, useState } from 'react'
import useQueryContext from '@hooks/useQueryContext'
import Link from 'next/link'
import { ChevronRightIcon } from '@heroicons/react/outline'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
interface Props {
inAccountDetails?: boolean
showView?: boolean
}
const NftBalanceCard = ({ inAccountDetails, showView }: Props) => {
const { fmtUrlWithCluster } = useQueryContext()
const wallet = useWalletOnePointOh()
const connected = !!wallet?.connected
const client = useVotePluginsClientStore(
(s) => s.state.currentRealmVotingClient
)
const nfts = useNftPluginStore((s) => s.state.votingNfts)
const isLoading = useNftPluginStore((s) => s.state.isLoadingNfts)
const connection = useWalletStore((s) => s.connection)
const [tokenOwnerRecordPk, setTokenOwneRecordPk] = useState('')
const {
tokenRecords,
realm,
symbol,
mint,
councilMint,
config,
realmInfo,
} = useRealm()
const { fetchRealm } = useWalletStore((s) => s.actions)
const ownTokenRecord = wallet?.publicKey
? tokenRecords[wallet.publicKey!.toBase58()]
: null
const handleRegister = async () => {
const instructions: TransactionInstruction[] = []
const { voterWeightPk } = await getVoterWeightRecord(
realm!.pubkey,
realm!.account.communityMint,
wallet!.publicKey!,
client.client!.program.programId
)
const createVoterWeightRecordIx = await (client.client as NftVoterClient).program.methods
.createVoterWeightRecord(wallet!.publicKey!)
.accounts({
voterWeightRecord: voterWeightPk,
governanceProgramId: realm!.owner,
realm: realm!.pubkey,
realmGoverningTokenMint: realm!.account.communityMint,
payer: wallet!.publicKey!,
systemProgram: SYSTEM_PROGRAM_ID,
})
.instruction()
instructions.push(createVoterWeightRecordIx)
await withCreateTokenOwnerRecord(
instructions,
realm!.owner!,
realmInfo?.programVersion!,
realm!.pubkey,
wallet!.publicKey!,
realm!.account.communityMint,
wallet!.publicKey!
)
const transaction = new Transaction()
transaction.add(...instructions)
await sendTransaction({
transaction: transaction,
wallet: wallet!,
connection: connection.current,
signers: [],
sendingMessage: `Registering`,
successMessage: `Registered`,
})
await fetchRealm(realm?.owner, realm?.pubkey)
}
useEffect(() => {
const getTokenOwnerRecord = async () => {
const defaultMint =
!mint?.supply.isZero() ||
config?.account.communityTokenConfig.maxVoterWeightAddin
? realm!.account.communityMint
: !councilMint?.supply.isZero()
? realm!.account.config.councilMint
: undefined
const tokenOwnerRecordAddress = await getTokenOwnerRecordAddress(
realm!.owner,
realm!.pubkey,
defaultMint!,
wallet!.publicKey!
)
setTokenOwneRecordPk(tokenOwnerRecordAddress.toBase58())
}
if (realm && wallet?.connected) {
getTokenOwnerRecord()
}
// eslint-disable-next-line react-hooks/exhaustive-deps -- TODO please fix, it can cause difficult bugs. You might wanna check out https://bobbyhadz.com/blog/react-hooks-exhaustive-deps for info. -@asktree
}, [realm?.pubkey.toBase58(), wallet?.connected])
return (
<Wrapper inAccountDetails={inAccountDetails}>
<div className="flex items-center justify-between mb-4">
<h3 className="mb-0">Your NFTS</h3>
{showView && (
<Link
href={fmtUrlWithCluster(
`/dao/${symbol}/account/${tokenOwnerRecordPk}`
)}
>
<a
className={`default-transition flex items-center text-fgd-2 text-sm transition-all hover:text-fgd-3 ${
!connected || !tokenOwnerRecordPk
? 'opacity-50 pointer-events-none'
: ''
}`}
>
View
<ChevronRightIcon className="flex-shrink-0 w-6 h-6" />
</a>
</Link>
)}
</div>
<div className="space-y-4">
{!connected ? (
<div className={'text-xs text-white/50 mt-4'}>
Connect your wallet to see your NFTs
</div>
) : !isLoading ? (
<NFTSelector
onNftSelect={() => {
return null
}}
ownersPk={[wallet!.publicKey!]}
nftHeight="50px"
nftWidth="50px"
selectable={false}
predefinedNfts={nfts}
></NFTSelector>
) : (
<Loading></Loading>
)}
</div>
{connected && !ownTokenRecord && (
<Button className="w-full" onClick={handleRegister}>
Join
</Button>
)}
</Wrapper>
)
}
const Wrapper: FC<Props> = ({ children, inAccountDetails }) => {
if (inAccountDetails) {
return <div className="space-y-4 w-1/2">{children}</div>
} else {
return <>{children}</>
}
}
export default NftBalanceCard

View File

@ -56,8 +56,8 @@ import { TokenInfo } from '@utils/services/types'
export type TradeProps = { tokenAccount: AssetAccount }
export const SUPPORTED_TRADE_PLATFORMS = ['Raydium', 'Openbook']
/* const SUPPORTED_TRADE_PLATFORMS = ['Raydium', 'Openbook']
*/
type TradeForm = {
amount: number
limitPrice: number
@ -164,7 +164,7 @@ const formSchema = (
)
}
export const poseidonProgramId = new web3.PublicKey(
const poseidonProgramId = new web3.PublicKey(
'8TJjyzq3iXc48MgV6TD5DumKKwfWKU14Jr9pwgnAbpzs'
)

View File

@ -1,112 +0,0 @@
import React, { useEffect, useState } from 'react'
import { Governance, Proposal } from '@solana/spl-governance'
import dayjs from 'dayjs'
interface CountdownState {
days: number
hours: number
minutes: number
seconds: number
}
const ZeroCountdown: CountdownState = {
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
}
const isZeroCountdown = (state: CountdownState) =>
state.days === 0 &&
state.hours === 0 &&
state.minutes === 0 &&
state.seconds === 0
export function VoteCountdown({
proposal,
governance,
}: {
proposal: Proposal
governance: Governance
}) {
const [countdown, setCountdown] = useState(ZeroCountdown)
useEffect(() => {
if (proposal.isVoteFinalized()) {
setCountdown(ZeroCountdown)
return
}
const getTimeToVoteEnd = () => {
const now = dayjs().unix()
let timeToVoteEnd = proposal.isPreVotingState()
? governance.config.baseVotingTime
: (proposal.votingAt?.toNumber() ?? 0) +
governance.config.baseVotingTime -
now
if (timeToVoteEnd <= 0) {
return ZeroCountdown
}
const days = Math.floor(timeToVoteEnd / 86400)
timeToVoteEnd -= days * 86400
const hours = Math.floor(timeToVoteEnd / 3600) % 24
timeToVoteEnd -= hours * 3600
const minutes = Math.floor(timeToVoteEnd / 60) % 60
timeToVoteEnd -= minutes * 60
const seconds = Math.floor(timeToVoteEnd % 60)
return { days, hours, minutes, seconds }
}
const updateCountdown = () => {
const newState = getTimeToVoteEnd()
setCountdown(newState)
}
const interval = setInterval(() => {
updateCountdown()
}, 1000)
updateCountdown()
return () => clearInterval(interval)
}, [proposal, governance])
return (
<>
{isZeroCountdown(countdown) ? (
<div className="text-fgd-3">Voting ended</div>
) : (
<div className="flex items-center text-fgd-1 w-40">
<div className="mr-1 text-fgd-3">Ends</div>
{countdown && countdown.days > 0 && (
<>
<div className="bg-bkg-1 px-1 py-0.5 rounded">
{countdown.days}d
</div>
<span className="font-bold mx-0.5 text-fgd-3">:</span>
</>
)}
<div className="bg-bkg-1 px-1 py-0.5 rounded">{countdown.hours}h</div>
<span className="font-bold mx-0.5 text-fgd-3">:</span>
<div className="bg-bkg-1 px-1 py-0.5 rounded">
{countdown.minutes}m
</div>
{!countdown.days && (
<>
<span className="font-bold mx-0.5 text-fgd-3">:</span>
<div className="bg-bkg-1 px-1 py-0.5 rounded w-9">
{countdown.seconds}s
</div>
</>
)}
</div>
)}
</>
)
}

View File

@ -223,7 +223,7 @@ export default function InstructionCard({
)
}
export function InstructionProgram({
function InstructionProgram({
connection,
programId,
}: {
@ -322,7 +322,7 @@ export function InstructionProgram({
)
}
export function InstructionAccount({
function InstructionAccount({
endpoint,
index,
accountMeta,
@ -396,7 +396,7 @@ export function InstructionAccount({
)
}
export function InstructionData({
function InstructionData({
descriptor,
}: {
descriptor: InstructionDescriptor | undefined

View File

@ -22,7 +22,7 @@ import {
} from '@components/InstructionDataUI'
import { tryGetMint } from '@utils/tokens'
export const PERIOD = {
const PERIOD = {
SECOND: 1,
MINUTE: 60,
HOUR: 3600,
@ -33,9 +33,9 @@ export const PERIOD = {
YEAR: 365 * 24 * 3600, // 365 days
}
export const DEFAULT_DECIMAL_PLACES = 2
const DEFAULT_DECIMAL_PLACES = 2
export const formatPeriodOfTime = (period: number): string => {
const formatPeriodOfTime = (period: number): string => {
if (!period) return '0 seconds'
const years = period / PERIOD.YEAR
@ -108,12 +108,12 @@ function deserializeStreamInformationFromData(
}
}
export interface TokenMintMetadata {
interface TokenMintMetadata {
readonly decimals: number
readonly symbol: string
}
export async function getMintMetadata(
async function getMintMetadata(
connection: Connection,
tokenMintPk: PublicKey
): Promise<TokenMintMetadata> {
@ -130,7 +130,7 @@ export async function getMintMetadata(
}
// Mint metadata for Well known tokens displayed on the instruction card
export const MINT_METADATA = {
const MINT_METADATA = {
Gssm3vfi8s65R31SBdmQRq6cKeYojGgup7whkw4VCiQj: { symbol: 'STRM', decimals: 9 },
}

View File

@ -120,27 +120,27 @@ export const ACCOUNT_NAMES = {
// Physis DAO
'29epeLvAMyRXtpA1HaoKB1hGcAnrc1NvMCbaZ8AVRwEi': 'Physis DAO Treasury',
'4i2Yjk5bUiLeVNwqBpkRdFSECSCvMgKoeCSdRSx1TPcz': 'DAO: Rewards (PHY)',
'EUkYhtkRmxQpnKTvGayBJM3Pt1FQNjaMWP3UCUb38hJN': 'DAO: Grants (PHY)',
EUkYhtkRmxQpnKTvGayBJM3Pt1FQNjaMWP3UCUb38hJN: 'DAO: Grants (PHY)',
'3XwmcRf9R6TFqCwhLkftur8Baq45ZYE7DQDj9WUAPsmN': 'DAO: Governance (PHY)',
'6Va7K51FRbnPcYZTUwkoFfoYtnfh8qyJaZqT4W1GGxVi': 'Physis EcoSystem Treasury',
'C2KKuAq4UaUFYtm3zcxZMSDUuSEfPSk4yLcq5XaBr4wM': 'EcoSystem: Development (PHY)',
'F6EHstw5jkmHVLLXj9HEx3xCRsY7Whm7JK266jWFrFSB': 'EcoSystem: CapEX (PHY)',
C2KKuAq4UaUFYtm3zcxZMSDUuSEfPSk4yLcq5XaBr4wM: 'EcoSystem: Development (PHY)',
F6EHstw5jkmHVLLXj9HEx3xCRsY7Whm7JK266jWFrFSB: 'EcoSystem: CapEX (PHY)',
'4gr1JjLD89VAbmQRrLeFDiLFSv2z2zn1tXRWRX4C3kow': 'EcoSystem: OpEX (PHY)',
'8eJoFYj8XtwJ9mER7qmb1EEnV8mGYGHyjxRct8ooJXQr': 'EcoSystem: Marketing (PHY)',
'2jfAMh48b37bBTKkoNwmvNZAqVQc1G7gh5vYv5FoWTUR': 'Physis Team Treasury',
'8vXYj8B567R8Di7BUvquiGC7usyPMtL756xx6KERfW9K': 'Team: Community (PHY)',
'AiGCc2YEwLNER7DETRwv5e82eqLwPL8FMcmmHEhED5Vr': 'Team: Core (PHY)',
'CpB6PDoxfkg2U8EC8XhyD6TdCAWkhRqZ4Fa3j3UFW6Rv': 'Team: Extraordinary (PHY)',
AiGCc2YEwLNER7DETRwv5e82eqLwPL8FMcmmHEhED5Vr: 'Team: Core (PHY)',
CpB6PDoxfkg2U8EC8XhyD6TdCAWkhRqZ4Fa3j3UFW6Rv: 'Team: Extraordinary (PHY)',
'BaT8NdFHAhrBpS7gTQX2YgSwazeNLcA4gKooDsAutvCk': 'Physis Alliance Treasury',
'H4WWxBJoDfGWfE212SF5tcyo75zBJnzCRAUmWpRMcxyH': 'Alliance: Partnerships (PHY)',
BaT8NdFHAhrBpS7gTQX2YgSwazeNLcA4gKooDsAutvCk: 'Physis Alliance Treasury',
H4WWxBJoDfGWfE212SF5tcyo75zBJnzCRAUmWpRMcxyH: 'Alliance: Partnerships (PHY)',
'5L84NZfjdfWHkkkUT9bJ8jKqtTMrpKsAobtTW4NKpJB1': 'Alliance: Advisors (PHY)',
'E26u3zGmYtR4tnmbhNSQS6kLVmSizSvPCQyu7qGnTWQ3': 'Physis Reserve Treasury',
'BgDFLAE25QybqyK6TMPdPF7vFTrBu1AjPs2cFkF8R3cb': 'Reserve: Seed (PHY)',
'GDJKzWrkxWHEPPt4k2Ao1TL7S1CEo4xNRnTAVk3jrmbk': 'Reserve: Launchpad (PHY)',
E26u3zGmYtR4tnmbhNSQS6kLVmSizSvPCQyu7qGnTWQ3: 'Physis Reserve Treasury',
BgDFLAE25QybqyK6TMPdPF7vFTrBu1AjPs2cFkF8R3cb: 'Reserve: Seed (PHY)',
GDJKzWrkxWHEPPt4k2Ao1TL7S1CEo4xNRnTAVk3jrmbk: 'Reserve: Launchpad (PHY)',
// GM DAO
'7WbRWL33mM3pbFLvuqNjBztihQtHWWFPGr4HLHyqViG9': 'Team funds',
@ -267,10 +267,6 @@ export function getAccountName(accountPk: PublicKey | string) {
return ACCOUNT_NAMES[key] ?? getProgramName(accountPk)
}
export const CHAT_PROGRAM_ID = new PublicKey(
'7fjWgipzcHFP3c5TMMWumFHNAL5Eme1gFqqRGnNPbbfG'
)
export const WSOL_MINT = 'So11111111111111111111111111111111111111112'
export const WSOL_MINT_PK = new PublicKey(WSOL_MINT)
@ -290,7 +286,7 @@ const HIDDEN_MNGO_TREASURES = [
]
//owner and desired accounts we want to show
export const MNGO_AUXILIARY_TOKEN_ACCOUNTS = [
const MNGO_AUXILIARY_TOKEN_ACCOUNTS = [
{
owner: '9BVcYqEQxyccuwznvxXqDkSJFavvTyheiTYk231T1A8S',
accounts: ['59BEyxwrFpt3x4sZ7TcXC3bHx3seGfqGkATcDx6siLWy'],
@ -313,7 +309,7 @@ export const ALL_CASTLE_PROGRAMS = [
PROGRAM_IDS['mainnet'],
]
export interface AccountDescriptor {
interface AccountDescriptor {
name: string
important?: boolean
}

View File

@ -1,21 +0,0 @@
import Button from '@components/Button'
import AdvancedOptionsDropdown from '@components/NewRealmWizard/components/AdvancedOptionsDropdown'
interface Props {
className?: string
}
export default function AuctionSize({ className }: Props) {
return (
<section className={className}>
<h4 className="mb-3">Size</h4>
<div className="flex space-x-3">
<Button className="w-1/3">Small Auction</Button>
<Button className="w-1/3">Medium Auction</Button>
<Button className="w-1/3">Large Auction</Button>
</div>
<AdvancedOptionsDropdown className="mt-5">asd</AdvancedOptionsDropdown>
</section>
)
}

View File

@ -1,348 +0,0 @@
// import Button from '@components/Button'
// import Input from '@components/inputs/Input'
// import { useEffect, useState } from 'react'
// import { Token } from '@models/treasury/Asset'
// import { BuyForm } from './models'
// import { MANGO_AUCTION_PROGRAM_ID } from './tools'
// import AdditionalProposalOptions from '@components/AdditionalProposalOptions'
// import { Keypair, PublicKey, TransactionInstruction } from '@solana/web3.js'
// import useWalletStore from 'stores/useWalletStore'
// import {
// createInitOpenOrdersInstructions,
// createNewOrderInstructions,
// getOpenOrdersPk,
// getOrderHistoryPk,
// getCreateDefaultFeeAtas,
// AuctionObj,
// fetchAuction,
// toNumberFromFp32,
// createNewEncryptedOrderInstructions,
// } from 'auction-house-sdk/sdk'
// import { getAssociatedTokenAddress } from '@blockworks-foundation/mango-v4'
// import {
// ASSOCIATED_TOKEN_PROGRAM_ID,
// Token as SPL_TOKEN,
// TOKEN_PROGRAM_ID,
// } from '@solana/spl-token'
// import useCreateProposal from '@hooks/useCreateProposal'
// import useQueryContext from '@hooks/useQueryContext'
// import useRealm from '@hooks/useRealm'
// import { useRouter } from 'next/router'
// import { InstructionDataWithHoldUpTime } from 'actions/createProposal'
// import { serializeInstructionToBase64 } from '@solana/spl-governance'
// import { UiInstruction } from '@utils/uiTypes/proposalCreationTypes'
// import { notify } from '@utils/notifications'
// import { Auction, OpenOrders } from 'auction-house-sdk/generated/accounts'
// import { tryParseKey } from '@tools/validators/pubkey'
// import Slider from '@components/Slider'
// import { tryGetMint } from '@utils/tokens'
// // import * as nacl from 'tweetnacl'
// interface Props {
// className?: string
// asset: Token
// }
export default function Buy() {
// const DEFAULT_TITLE = `Buy tokens on auction`
// const DEFAULT_DESCRIPTION = `Buy tokens on auction`
// const wallet = useWalletOnePointOh()
// const connection = useWalletStore((s) => s.connection)
// const { symbol } = useRealm()
// const router = useRouter()
// const { handleCreateProposal } = useCreateProposal()
// const { fmtUrlWithCluster } = useQueryContext()
// const [currentAuction, setCurrentAuction] = useState<Auction | null>()
// const [form, setForm] = useState<BuyForm>({
// amount: 0,
// deposit: 0,
// price: 0,
// auctionPk: '',
// })
// const [formErrors, setFormErrors] = useState({})
// const [proposalInfo, setProposalInfo] = useState({
// title: '',
// description: '',
// voteByCouncil: false,
// })
// useEffect(() => {
// const pubkey = tryParseKey(form.auctionPk)
// const getAuction = async () => {
// const auction = await fetchAuction(connection.current, pubkey!)
// if (auction.quoteMint.toBase58() !== asset.mintAddress) {
// notify({
// type: 'error',
// message: 'Selected token does not match auction quote token',
// })
// }
// setCurrentAuction(auction)
// }
// if (pubkey) {
// getAuction()
// } else {
// setCurrentAuction(null)
// }
// // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO please fix, it can cause difficult bugs. You might wanna check out https://bobbyhadz.com/blog/react-hooks-exhaustive-deps for info. -@asktree
// }, [form.auctionPk])
// const handleSetForm = ({ propertyName, value }) => {
// setFormErrors({})
// setForm({ ...form, [propertyName]: value })
// }
// const handlePropose = async (newAuctionObj: AuctionObj | null) => {
// const auctionPk = new PublicKey(form.auctionPk)
// const auction = await fetchAuction(connection.current, auctionPk)
// const assetExtenstions = asset.raw.extensions
// const governance = asset.raw.governance
// const authority = assetExtenstions.token?.account.owner
// const auctionId = auction!.auctionId
// const auctionAuthroity = auction!.authority
// const quoteMint = auction!.quoteMint
// const tickSize = auction!.tickSize
// const quoteVault = auction!.quoteVault
// const eventQueue = auction!.eventQueue
// const bids = auction!.bids
// const asks = auction!.asks
// const baseMint = auction!.baseMint
// const baseVault = auction!.baseVault
// const perquisiteInstructions: TransactionInstruction[] = newAuctionObj
// ? [...newAuctionObj.transactionInstructions]
// : []
// const perquisiteSingers: Keypair[] = newAuctionObj
// ? [...newAuctionObj.signers]
// : []
// const transactionInstructions: TransactionInstruction[] = []
// const openOrdersPk = await getOpenOrdersPk(
// authority!,
// auctionId,
// auctionAuthroity,
// MANGO_AUCTION_PROGRAM_ID
// )
// const openOrders = await OpenOrders.fetch(connection.current, openOrdersPk)
// if (!openOrders) {
// const {
// quoteFeeAta,
// baseFeeAta,
// instructions,
// } = await getCreateDefaultFeeAtas({
// wallet: wallet!,
// connection: connection.current,
// baseMint: auction.baseMint,
// quoteMint: auction.quoteMint,
// cluster: connection.cluster,
// })
// perquisiteInstructions.push(...instructions)
// const orderHistoryPk = await getOrderHistoryPk(
// assetExtenstions.token!.account.owner,
// auctionId,
// auctionAuthroity,
// MANGO_AUCTION_PROGRAM_ID
// )
// transactionInstructions.push(
// ...createInitOpenOrdersInstructions({
// authority: authority!,
// auctionPk: auctionPk,
// openOrdersPk: openOrdersPk,
// orderHistoryPk: orderHistoryPk,
// baseFeePk: baseFeeAta,
// quoteFeePk: quoteFeeAta,
// side: 'Bid',
// })
// )
// }
// const baseAta = await getAssociatedTokenAddress(
// baseMint, // mint
// assetExtenstions.token!.account.owner, // owner
// true
// )
// const baseAtaAcc = await connection.current.getParsedAccountInfo(baseAta)
// if (!baseAtaAcc?.value) {
// const ataCreateionIx = SPL_TOKEN.createAssociatedTokenAccountInstruction(
// ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID
// TOKEN_PROGRAM_ID, // always TOKEN_PROGRAM_ID
// baseMint, // mint
// baseAta, // ata
// assetExtenstions.token!.account.owner, // owner of token account
// wallet!.publicKey! // fee payer
// )
// perquisiteInstructions.push(ataCreateionIx)
// }
// const localOrderKey = nacl.box.keyPair()
// const baseMintAcc = await tryGetMint(
// connection.current,
// currentAuction!.baseMint
// )
// transactionInstructions.push(
// ...(!currentAuction?.areBidsEncrypted
// ? createNewOrderInstructions({
// price: Number(form.price),
// amount: Number(form.amount),
// baseDecimals: assetExtenstions.mint!.account.decimals,
// authority: authority!,
// auctionPk: auctionPk,
// openOrdersPk: openOrdersPk,
// quoteToken: assetExtenstions.token!.publicKey,
// baseToken: baseAta,
// tickSize: tickSize,
// quoteMint: quoteMint,
// quoteVault: quoteVault,
// eventQueue: eventQueue,
// bids: bids,
// asks: asks,
// baseMint: baseMint,
// baseVault: baseVault,
// })
// : createNewEncryptedOrderInstructions({
// price: Number(form.price),
// amount: Number(form.amount),
// baseDecimals: baseMintAcc!.account.decimals,
// quoteDecimals: assetExtenstions.mint!.account.decimals,
// deposit: form.deposit,
// openOrdersPk: openOrdersPk,
// authority: authority!,
// localOrderKey: localOrderKey,
// quoteToken: assetExtenstions.token!.publicKey,
// baseToken: baseAta,
// auctionPk,
// tickSize,
// naclPubkey: currentAuction.naclPubkey,
// quoteMint,
// quoteVault,
// baseMint,
// baseVault,
// }))
// )
// const instructionsData = transactionInstructions.map((x, idx) => {
// const obj: UiInstruction = {
// serializedInstruction: serializeInstructionToBase64(x),
// isValid: true,
// governance,
// prerequisiteInstructions: idx === 0 ? perquisiteInstructions : [],
// prerequisiteInstructionsSigners: idx === 0 ? perquisiteSingers : [],
// chunkBy: 1,
// chunkSplitByDefault: true,
// }
// return new InstructionDataWithHoldUpTime({
// instruction: obj,
// governance,
// })
// })
// try {
// const proposalAddress = await handleCreateProposal({
// title: proposalInfo.title ? proposalInfo.title : DEFAULT_TITLE,
// description: proposalInfo.description
// ? proposalInfo.description
// : DEFAULT_DESCRIPTION,
// voteByCouncil: proposalInfo.voteByCouncil,
// instructionsData: instructionsData,
// governance: governance,
// })
// const url = fmtUrlWithCluster(
// `/dao/${symbol}/proposal/${proposalAddress}`
// )
// router.push(url)
// } catch (ex) {
// notify({ type: 'error', message: `${ex}` })
// }
// }
return (
<>
{/* <section className={`${className} space-y-3`}>
<h4>Details</h4>
<Input
label="Auction Pk"
value={form.auctionPk}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'auctionPk',
})
}
error={formErrors['auctionPk']}
/>
<Input
label="Amount"
value={form.amount}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'amount',
})
}
error={formErrors['amount']}
/>
<Input
label="Price"
value={form.price}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'price',
})
}
error={formErrors['price']}
/>
{currentAuction?.areBidsEncrypted && (
<div className="pb-6 pt-3">
<div className="text-xs">
Deposit more to hide your actual bid: {form.deposit}
</div>
<Slider
disabled={false}
step={toNumberFromFp32(currentAuction.tickSize)}
min={Number(form.amount) * Number(form.price)}
max={
Number(asset.raw.extensions.amount?.toNumber()) /
10 ** asset.raw.extensions.mint!.account.decimals
}
value={form.deposit}
onChange={(d) =>
handleSetForm({
value: Number(d),
propertyName: 'deposit',
})
}
/>
</div>
)}
<AdditionalProposalOptions
title={proposalInfo.title}
description={proposalInfo.description}
defaultTitle={DEFAULT_TITLE}
defaultDescription={DEFAULT_DESCRIPTION}
setTitle={(evt) =>
setProposalInfo((prev) => ({ ...prev, title: evt.target.value }))
}
setDescription={(evt) =>
setProposalInfo((prev) => ({
...prev,
description: evt.target.value,
}))
}
voteByCouncil={proposalInfo.voteByCouncil}
setVoteByCouncil={(val) =>
setProposalInfo((prev) => ({
...prev,
voteByCouncil: val,
}))
}
/>
<div className="flex justify-end">
<Button onClick={() => handlePropose(null)}>Propose</Button>
</div>
</section> */}
</>
)
}

View File

@ -1,21 +0,0 @@
import Modal from '@components/Modal'
//import { Token } from '@models/treasury/Asset'
import Buy from './Buy'
//import { createAuctionInstructions } from 'auction-house/sdk/auction'
interface Props {
isOpen: boolean
//asset: Token
onClose: () => void
}
export default function BuyModal({ onClose, isOpen }: Props) {
return isOpen ? (
<Modal onClose={onClose} isOpen={isOpen}>
<>
<h3 className="mb-4 flex items-center">Buy tokens</h3>
<Buy></Buy>
</>
</Modal>
) : null
}

View File

@ -1,594 +0,0 @@
// import Button from '@components/Button'
// import Input from '@components/inputs/Input'
// import AdvancedOptionsDropdown from '@components/NewRealmWizard/components/AdvancedOptionsDropdown'
// import { useEffect, useState } from 'react'
// import { Token } from '@models/treasury/Asset'
// import Checkbox from '@components/inputs/Checkbox'
// import { ParticipantPreset, SellForm } from './models'
// import { MANGO_AUCTION_PROGRAM_ID, paramsForTokenSale } from './tools'
// import TokenMintInput from '@components/inputs/TokenMintInput'
// import AdditionalProposalOptions from '@components/AdditionalProposalOptions'
// import { abbreviateAddress } from '@utils/formatting'
// import { tryParsePublicKey } from '@tools/core/pubkey'
// import { Keypair, PublicKey, TransactionInstruction } from '@solana/web3.js'
// import useWalletStore from 'stores/useWalletStore'
// import Modal from '@components/Modal'
// import dayjs from 'dayjs'
// import {
// createInitOpenOrdersInstructions,
// createNewOrderInstructions,
// getOpenOrdersPk,
// getOrderHistoryPk,
// getCreateDefaultFeeAtas,
// createAuctionInstructions,
// AuctionObj,
// fetchAuction,
// } from 'auction-house-sdk/sdk'
// import { getAssociatedTokenAddress } from '@blockworks-foundation/mango-v4'
// import {
// ASSOCIATED_TOKEN_PROGRAM_ID,
// Token as SPL_TOKEN,
// TOKEN_PROGRAM_ID,
// } from '@solana/spl-token'
// import useCreateProposal from '@hooks/useCreateProposal'
// import useQueryContext from '@hooks/useQueryContext'
// import useRealm from '@hooks/useRealm'
// import { useRouter } from 'next/router'
// import { InstructionDataWithHoldUpTime } from 'actions/createProposal'
// import { serializeInstructionToBase64 } from '@solana/spl-governance'
// import { UiInstruction } from '@utils/uiTypes/proposalCreationTypes'
// import { notify } from '@utils/notifications'
// import Switch from '@components/Switch'
// import { OpenOrders } from 'auction-house-sdk/generated/accounts'
// interface Props {
// className?: string
// asset: Token
// }
// const DEFAULT_TOKENS_FOR_SALE = 1
// const DEFAULT_MIN_PRICE = 1
export default function Sell() {
// const wallet = useWalletOnePointOh()
// const connection = useWalletStore((s) => s.connection)
// const formatter = Intl.NumberFormat('en', {
// notation: 'compact',
// })
// const { symbol } = useRealm()
// const router = useRouter()
// const { handleCreateProposal } = useCreateProposal()
// const { fmtUrlWithCluster } = useQueryContext()
// const [openSaveBackupKeyModal, setOpenSaveBackupKeyModal] = useState(false)
// const [auctionObj, setAuctionObj] = useState<AuctionObj | null>(null)
// const [fileDownloaded, setFileDownloaded] = useState(false)
// const [auctionSize, setAuctionSize] = useState<number>(ParticipantPreset.M)
// const [withCreateAuction, setWithCreateAuction] = useState(true)
// const [form, setForm] = useState<SellForm>({
// auctionPk: '',
// baseMint: asset.raw.extensions.mint!.publicKey.toBase58(),
// quoteMint: '',
// areAsksEncrypted: false,
// areBidsEncrypted: true,
// maxOrders: 4,
// orderPhaseLength: 24 * 60 * 60,
// tokensForSale: DEFAULT_TOKENS_FOR_SALE,
// minPrice: DEFAULT_MIN_PRICE,
// ...paramsForTokenSale(
// ParticipantPreset.M,
// DEFAULT_TOKENS_FOR_SALE,
// DEFAULT_MIN_PRICE
// ),
// })
// const DEFAULT_TITLE = `Sell ${form.tokensForSale} ${
// asset.name ? asset.name : abbreviateAddress(asset.id)
// } on auction`
// const DEFAULT_DESCRIPTION = `Sell ${form.tokensForSale} ${
// asset.name ? asset.name : abbreviateAddress(asset.id)
// } on auction for min price: ${form.minPrice}`
// const [proposalInfo, setProposalInfo] = useState({
// title: '',
// description: '',
// voteByCouncil: false,
// })
// const [formErrors, setFormErrors] = useState({})
// const handleSetForm = ({ propertyName, value }) => {
// setFormErrors({})
// setForm({ ...form, [propertyName]: value })
// }
// const sizeBtnClass = (size: number) => {
// const classnames = `text-xs ${size === auctionSize ? 'bg-fgd-1' : ''}`
// return classnames
// }
// const closeSaveKeyPrompt = () => {
// setOpenSaveBackupKeyModal(false)
// setAuctionObj(null)
// setFileDownloaded(false)
// }
// const downloadBackupFile = async () => {
// // Create blob link to download
// const url = window.URL.createObjectURL(
// new Blob([JSON.stringify(auctionObj!.localAuctionKey)])
// )
// const link = document.createElement('a')
// link.href = url
// const timestamp = dayjs().unix()
// link.setAttribute(
// 'download',
// `keypair-backup-${auctionObj?.auctionPk.toBase58()}-${timestamp}.json`
// )
// // Append to html link element page
// document.body.appendChild(link)
// // Start download
// link.click()
// // Clean up and remove the link
// link.parentNode!.removeChild(link)
// setFileDownloaded(true)
// }
// const promptSaveKey = async (data: SellForm) => {
// const baseMintPk = tryParsePublicKey(data.baseMint)
// const quoteMintPk = tryParsePublicKey(data.quoteMint)
// if (!baseMintPk) {
// throw 'No baseMintPk'
// }
// if (!quoteMintPk) {
// throw 'No quoteMintPk'
// }
// const transactionInstructions: TransactionInstruction[] = []
// const auctionObj = await createAuctionInstructions({
// ...data,
// connection: connection.current,
// wallet: wallet!.publicKey!,
// programId: MANGO_AUCTION_PROGRAM_ID,
// baseMint: new PublicKey(data.baseMint),
// quoteMint: new PublicKey(data.quoteMint),
// baseDecimals: asset.raw.extensions.mint!.account.decimals,
// })
// auctionObj.transactionInstructions.unshift(...transactionInstructions)
// setAuctionObj(auctionObj)
// setOpenSaveBackupKeyModal(true)
// }
// const handlePropose = async (newAuctionObj: AuctionObj | null) => {
// const auctionPk = newAuctionObj
// ? newAuctionObj.auctionPk
// : new PublicKey(form.auctionPk)
// const existingAuction = !newAuctionObj
// ? await fetchAuction(connection.current, auctionPk)
// : null
// const assetExtenstions = asset.raw.extensions
// const newAuctionArgs = newAuctionObj?.auctionParams.args
// const newAuctionAccounts = newAuctionObj?.auctionParams.accounts
// const governance = asset.raw.governance
// const authority = assetExtenstions.token?.account.owner
// const auctionId = newAuctionArgs?.auctionId || existingAuction!.auctionId
// const auctionAuthroity =
// newAuctionAccounts?.authority || existingAuction!.authority
// const quoteMint =
// newAuctionAccounts?.quoteMint || existingAuction!.quoteMint
// const tickSize = newAuctionArgs?.tickSize || existingAuction!.tickSize
// const quoteVault =
// newAuctionAccounts?.quoteVault || existingAuction!.quoteVault
// const eventQueue =
// newAuctionAccounts?.eventQueue || existingAuction!.eventQueue
// const bids = newAuctionAccounts?.bids || existingAuction!.bids
// const asks = newAuctionAccounts?.asks || existingAuction!.asks
// const baseMint = newAuctionAccounts?.baseMint || existingAuction!.baseMint
// const baseVault =
// newAuctionAccounts?.baseVault || existingAuction!.baseVault
// const perquisiteInstructions: TransactionInstruction[] = newAuctionObj
// ? [...newAuctionObj.transactionInstructions]
// : []
// const perquisiteSingers: Keypair[] = newAuctionObj
// ? [...newAuctionObj.signers]
// : []
// const transactionInstructions: TransactionInstruction[] = []
// const openOrdersPk = await getOpenOrdersPk(
// authority!,
// auctionId,
// auctionAuthroity,
// MANGO_AUCTION_PROGRAM_ID
// )
// const openOrders = await OpenOrders.fetch(connection.current, openOrdersPk)
// if (!openOrders) {
// const {
// quoteFeeAta,
// baseFeeAta,
// instructions,
// } = await getCreateDefaultFeeAtas({
// wallet: wallet!,
// connection: connection.current,
// baseMint: new PublicKey(form.baseMint),
// quoteMint: new PublicKey(form.quoteMint),
// cluster: connection.cluster,
// })
// perquisiteInstructions.push(...instructions)
// const orderHistoryPk = await getOrderHistoryPk(
// assetExtenstions.token!.account.owner,
// auctionId,
// auctionAuthroity,
// MANGO_AUCTION_PROGRAM_ID
// )
// transactionInstructions.push(
// ...createInitOpenOrdersInstructions({
// authority: authority!,
// auctionPk: auctionPk,
// openOrdersPk: openOrdersPk,
// orderHistoryPk: orderHistoryPk,
// baseFeePk: baseFeeAta,
// quoteFeePk: quoteFeeAta,
// side: 'Ask',
// })
// )
// }
// const quoteAta = await getAssociatedTokenAddress(
// quoteMint, // mint
// assetExtenstions.token!.account.owner, // owner
// true
// )
// const quoteAtaAcc = await connection.current.getParsedAccountInfo(quoteAta)
// if (!quoteAtaAcc?.value) {
// const ataCreateionIx = SPL_TOKEN.createAssociatedTokenAccountInstruction(
// ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID
// TOKEN_PROGRAM_ID, // always TOKEN_PROGRAM_ID
// quoteMint, // mint
// quoteAta, // ata
// assetExtenstions.token!.account.owner, // owner of token account
// wallet!.publicKey! // fee payer
// )
// perquisiteInstructions.push(ataCreateionIx)
// }
// transactionInstructions.push(
// ...createNewOrderInstructions({
// price: form.minPrice,
// amount: form.tokensForSale,
// baseDecimals: assetExtenstions.mint!.account.decimals,
// authority: authority!,
// auctionPk: auctionPk,
// openOrdersPk: openOrdersPk,
// quoteToken: quoteAta,
// baseToken: assetExtenstions.token!.publicKey,
// tickSize: tickSize,
// quoteMint: quoteMint,
// quoteVault: quoteVault,
// eventQueue: eventQueue,
// bids: bids,
// asks: asks,
// baseMint: baseMint,
// baseVault: baseVault,
// })
// )
// const instructionsData = transactionInstructions.map((x, idx) => {
// const obj: UiInstruction = {
// serializedInstruction: serializeInstructionToBase64(x),
// isValid: true,
// governance,
// prerequisiteInstructions: idx === 0 ? perquisiteInstructions : [],
// prerequisiteInstructionsSigners: idx === 0 ? perquisiteSingers : [],
// chunkBy: 1,
// chunkSplitByDefault: true,
// }
// return new InstructionDataWithHoldUpTime({
// instruction: obj,
// governance,
// })
// })
// try {
// const proposalAddress = await handleCreateProposal({
// title: proposalInfo.title ? proposalInfo.title : DEFAULT_TITLE,
// description: proposalInfo.description
// ? proposalInfo.description
// : DEFAULT_DESCRIPTION,
// voteByCouncil: proposalInfo.voteByCouncil,
// instructionsData: instructionsData,
// governance: governance,
// })
// const url = fmtUrlWithCluster(
// `/dao/${symbol}/proposal/${proposalAddress}`
// )
// router.push(url)
// } catch (ex) {
// notify({ type: 'error', message: `${ex}` })
// }
// }
// useEffect(() => {
// setFormErrors({})
// const newFormValues = form.areBidsEncrypted
// ? {
// ...paramsForTokenSale(auctionSize, form.tokensForSale, form.minPrice),
// }
// : {
// ...paramsForTokenSale(auctionSize, form.tokensForSale, form.minPrice),
// decryptionPhaseLength: 0,
// }
// setForm({
// ...form,
// ...newFormValues,
// })
// // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO please fix, it can cause difficult bugs. You might wanna check out https://bobbyhadz.com/blog/react-hooks-exhaustive-deps for info. -@asktree
// }, [form.areBidsEncrypted, form.tokensForSale, form.minPrice, auctionSize])
// useEffect(() => {
// setFormErrors({})
// setForm({
// ...form,
// auctionPk: '',
// })
// // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO please fix, it can cause difficult bugs. You might wanna check out https://bobbyhadz.com/blog/react-hooks-exhaustive-deps for info. -@asktree
// }, [withCreateAuction])
return (
<>
{/* <section className={`${className} space-y-3`}>
<h4>Witch create auction</h4>
<div className="flex flex-row text-xs items-center">
<Switch
checked={withCreateAuction}
onChange={(checked) => setWithCreateAuction(checked)}
/>
</div>
{withCreateAuction && (
<>
<h4>Size based on number of participants</h4>
<div className="grid gap-4 grid-cols-2">
{Object.values(ParticipantPreset)
.filter((x) => typeof x === 'string')
.map((key) => (
<Button
key={key}
onClick={() => setAuctionSize(ParticipantPreset[key])}
className={sizeBtnClass(ParticipantPreset[key])}
>
{key} Auction {formatter.format(ParticipantPreset[key])}
</Button>
))}
</div>
</>
)}
<h4>Details</h4>
{!withCreateAuction && (
<Input
label="Auction Pk"
value={form.auctionPk}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'auctionPk',
})
}
error={formErrors['auctionPk']}
/>
)}
<Input
label="Tokens for sale"
value={form.tokensForSale}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'tokensForSale',
})
}
error={formErrors['tokensForSale']}
/>
<Input
label="Min price"
value={form.minPrice}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'minPrice',
})
}
error={formErrors['minPrice']}
/>
{withCreateAuction && (
<>
<Input
label="Max orders per users"
value={form.maxOrders}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'maxOrders',
})
}
error={formErrors['maxOrders']}
/>
<Input
label="Order phase length (sec)"
value={form.orderPhaseLength}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'orderPhaseLength',
})
}
error={formErrors['orderPhaseLength']}
/>
<div className="mt-3 py-3">
<Checkbox
checked={form.areBidsEncrypted}
label="Encrypt bids"
onChange={(evt) =>
handleSetForm({
value: evt.target.checked,
propertyName: 'areBidsEncrypted',
})
}
error={formErrors['areBidsEncrypted']}
/>
</div>
<TokenMintInput
label={'Quote mint'}
onValidMintChange={(mintAddress, tokenInfo) => {
if (mintAddress) {
handleSetForm({
value: mintAddress,
propertyName: 'quoteMint',
})
}
if (tokenInfo) {
handleSetForm({
value: tokenInfo.address,
propertyName: 'quoteMint',
})
}
}}
/>
<div>
<AdvancedOptionsDropdown
title="Advanced auction options"
className="my-5"
>
<div className="space-y-3">
<Input
label="Min Base Order Size"
value={form.minBaseOrderSize}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'minBaseOrderSize',
})
}
error={formErrors['minBaseOrderSize']}
/>
<Input
label="Tick Size"
value={form.tickSize}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'tickSize',
})
}
error={formErrors['tickSize']}
/>
<Input
label="Decryption Phase Length"
value={form.decryptionPhaseLength}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'decryptionPhaseLength',
})
}
error={formErrors['decryptionPhaseLength']}
/>
<Input
label="Event Queue Bytes"
value={form.eventQueueBytes}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'eventQueueBytes',
})
}
error={formErrors['eventQueueBytes']}
/>
<Input
label="Bids Bytes"
value={form.bidsBytes}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'bidsBytes',
})
}
error={formErrors['bidsBytes']}
/>
<Input
label="Asks Bytes"
value={form.asksBytes}
type="text"
onChange={(evt) =>
handleSetForm({
value: evt.target.value,
propertyName: 'asksBytes',
})
}
error={formErrors['asksBytes']}
/>
</div>
</AdvancedOptionsDropdown>
</div>
</>
)}
<AdditionalProposalOptions
title={proposalInfo.title}
description={proposalInfo.description}
defaultTitle={DEFAULT_TITLE}
defaultDescription={DEFAULT_DESCRIPTION}
setTitle={(evt) =>
setProposalInfo((prev) => ({ ...prev, title: evt.target.value }))
}
setDescription={(evt) =>
setProposalInfo((prev) => ({
...prev,
description: evt.target.value,
}))
}
voteByCouncil={proposalInfo.voteByCouncil}
setVoteByCouncil={(val) =>
setProposalInfo((prev) => ({
...prev,
voteByCouncil: val,
}))
}
/>
<div className="flex justify-end">
<Button
onClick={() =>
withCreateAuction ? promptSaveKey(form) : handlePropose(null)
}
>
Propose
</Button>
</div>
</section>
{openSaveBackupKeyModal && (
<Modal onClose={closeSaveKeyPrompt} isOpen={openSaveBackupKeyModal}>
<div className="mb-1.5 flex flex-col text-th-fgd-2 items-center">
<div className="mb-3">
Please save your keypair backup file and do not share it with
anyone it will be needed to finish the auction
</div>
<div>
<Button className="mb-5" onClick={downloadBackupFile}>
Download backup file
</Button>
</div>
<Button
disabled={!fileDownloaded}
tooltipMessage={
!fileDownloaded ? 'Download file to start auction' : ''
}
onClick={() => handlePropose(auctionObj!)}
>
Create auction
</Button>
</div>
</Modal>
)} */}
</>
)
}

View File

@ -1,21 +0,0 @@
import Modal from '@components/Modal'
//import { Token } from '@models/treasury/Asset'
import Sell from './Sell'
//import { createAuctionInstructions } from 'auction-house/sdk/auction'
interface Props {
isOpen: boolean
//asset: Token
onClose: () => void
}
export default function SellModal({ onClose, isOpen }: Props) {
return isOpen ? (
<Modal onClose={onClose} isOpen={isOpen}>
<>
<h3 className="mb-4 flex items-center">Sell tokens</h3>
<Sell></Sell>
</>
</Modal>
) : null
}

View File

@ -1,31 +0,0 @@
export enum ParticipantPreset {
S = 1000,
M = 10_000,
L = 100_000,
XL = 1_000_000,
}
export interface SellForm {
baseMint: string
quoteMint: string
areAsksEncrypted: boolean
areBidsEncrypted: boolean
minBaseOrderSize: number
tickSize: number
orderPhaseLength: number
decryptionPhaseLength: number
eventQueueBytes: number
bidsBytes: number
asksBytes: number
maxOrders: number
tokensForSale: number
minPrice: number
auctionPk: string
}
export interface BuyForm {
amount: number
price: number
deposit: number
auctionPk: string
}

View File

@ -1,20 +0,0 @@
import { PublicKey } from '@solana/web3.js'
export const paramsForTokenSale = function (
participants: number,
tokensForSale: number,
reservePrice: number
) {
return {
minBaseOrderSize: tokensForSale / participants,
tickSize: reservePrice / 10000,
decryptionPhaseLength: 60 * 60 + participants / 10, // 60min + 10 participants per second
eventQueueBytes: 1024 * 200, // 1024 events, 200 bytes per event
bidsBytes: participants * 16, // 16 bytes per participant
asksBytes: 64 * 16, // allow 64 asks for selling side
}
}
export const MANGO_AUCTION_PROGRAM_ID = new PublicKey(
'AReGQtE8e1WC1ztXXq5edtBBPngicGLfLnWeMP7E5WXq'
)

View File

@ -2,40 +2,6 @@ import { ExternalLinkIcon } from '@heroicons/react/outline'
import React from 'react'
import cx from 'classnames'
import Tooltip from '@components/Tooltip'
interface Props {
className?: string
address?: string
}
export default function ExploreLink(props: Props) {
return (
<Tooltip content={props.address ? undefined : 'Nothing selected'}>
<a
className={cx(
'flex',
'items-center',
'space-x-1',
'text-primary-light',
props.address ? 'cursor-pointer' : 'cursor-not-allowed',
!props.address && 'opacity-60'
)}
href={
props.address
? `https://explorer.solana.com/address/${props.address}`
: 'https://explorer.solana.com'
}
target="_blank"
rel="noreferrer"
>
<ExternalLinkIcon className="h-4 w-4" />
<div className="text-sm">Explorer</div>
</a>
</Tooltip>
)
}
export const ExploreButton = (props: {
address: string
className?: string

View File

@ -1,63 +0,0 @@
import Button from '@components/Button'
import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
import { Token } from '@models/treasury/Asset'
import { useState } from 'react'
import BuyModal from '../Auction/BuyModal'
import SellModal from '../Auction/SellModal'
interface Props {
className: string | undefined
asset: Token
}
export default function Auction(props: Props) {
const wallet = useWalletOnePointOh()
const connected = !!wallet?.connected
const [sellModalOpen, setSellModalOpen] = useState(false)
const closeSellModal = () => {
setSellModalOpen(false)
}
const openSellModal = () => {
setSellModalOpen(true)
}
const [buyModalOpen, setBuyModalOpen] = useState(false)
const closeBuyModal = () => {
setBuyModalOpen(false)
}
const openBuyModal = () => {
setBuyModalOpen(true)
}
return (
<div className={props.className}>
<header className="mb-3">
<div className="text-fgd-1 text-lg font-bold">Auction</div>
</header>
<section className="overflow-y-auto flex-grow space-y-4 space-x-4">
<Button
disabled={!connected}
tooltipMessage={!connected ? 'Please connect your wallet' : ''}
onClick={openSellModal}
>
Sell
</Button>
<Button
disabled={!connected}
tooltipMessage={!connected ? 'Please connect your wallet' : ''}
onClick={openBuyModal}
>
Buy
</Button>
<SellModal
//asset={props.asset}
isOpen={sellModalOpen}
onClose={closeSellModal}
></SellModal>
<BuyModal
//asset={props.asset}
isOpen={buyModalOpen}
onClose={closeBuyModal}
></BuyModal>
</section>
</div>
)
}

View File

@ -1,20 +0,0 @@
import React from 'react'
type Props = React.SVGAttributes<SVGElement>
export default function OtherPreviewIcon(props: Props) {
return (
<svg
{...props}
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M5.79996 12.9C5.88134 12.839 5.94217 12.7546 5.97434 12.6581L6.36038 11.5H9.63962L10.0257 12.6581C10.0578 12.7546 10.1187 12.839 10.2 12.9L10.9997 13.4997H5.00026L5.79996 12.9ZM10 10.5H6H3.33333C2.8731 10.5 2.5 10.1269 2.5 9.66667V3.33333C2.5 2.8731 2.8731 2.5 3.33333 2.5H12.6667C13.1269 2.5 13.5 2.8731 13.5 3.33333V9.66667C13.5 10.1269 13.1269 10.5 12.6667 10.5H10Z"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
}

View File

@ -1,35 +0,0 @@
import React from 'react'
type Props = React.SVGAttributes<SVGElement>
export default function WalletIcon(props: Props) {
return (
<svg
{...props}
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M2 12V4C2 2.89543 2.89543 2 4 2H11C11.5523 2 12 2.44772 12 3V5H13C13.5523 5 14 5.44772 14 6V13C14 13.5523 13.5523 14 13 14H4C2.89543 14 2 13.1046 2 12ZM4 5C3.44772 5 3 4.55228 3 4C3 3.44772 3.44772 3 4 3H11V5H4ZM11 10C11.5523 10 12 9.55228 12 9C12 8.44772 11.5523 8 11 8C10.4477 8 10 8.44772 10 9C10 9.55228 10.4477 10 11 10Z"
fill="url(#paint0_linear_6033_21552)"
/>
<defs>
<linearGradient
id="paint0_linear_6033_21552"
x1="2"
y1="8.6"
x2="14.0053"
y2="8.73611"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#00C2FF" />
<stop offset="0.5" stopColor="#00E4FF" />
<stop offset="1" stopColor="#87F2FF" />
</linearGradient>
</defs>
</svg>
)
}

View File

@ -1,20 +1,4 @@
import { useState, useRef, useEffect } from 'react'
export function useEffectAfterTimeout(effect, timeout) {
useEffect(() => {
const handle = setTimeout(effect, timeout)
return () => clearTimeout(handle)
})
}
export function useListener(emitter, eventName) {
const [, forceUpdate] = useState(0)
useEffect(() => {
const listener = () => forceUpdate((i) => i + 1)
emitter.on(eventName, listener)
return () => emitter.removeListener(eventName, listener)
}, [emitter, eventName])
}
import { useRef, useEffect } from 'react'
export default function useInterval(callback, delay) {
const savedCallback = useRef<() => void>()

View File

@ -1,60 +0,0 @@
import { useEffect, useState } from 'react'
const SANCTIONED_COUNTRIES = [
{ country: 'Antigua and Barbuda', code: 'AG' },
{ country: 'Algeria', code: 'DZ' },
{ country: 'Bangladesh', code: 'BD' },
{ country: 'Bolivia', code: 'BO' },
{ country: 'Belarus', code: 'BY' },
{ country: 'Burundi', code: 'BI' },
{ country: 'Burma (Myanmar)', code: 'MM' },
{ country: "Cote D'Ivoire (Ivory Coast)", code: 'CI' },
{ country: 'Cuba', code: 'CU' },
{ country: 'Democratic Republic of Congo', code: 'CD' },
{ country: 'Ecuador', code: 'EC' },
{ country: 'Iran', code: 'IR' },
{ country: 'Iraq', code: 'IQ' },
{ country: 'Liberia', code: 'LR' },
{ country: 'Libya', code: 'LY' },
{ country: 'Mali', code: 'ML' },
{ country: 'Morocco', code: 'MA' },
{ country: 'Nepal', code: 'NP' },
{ country: 'North Korea', code: 'KP' },
{ country: 'Somalia', code: 'SO' },
{ country: 'Sudan', code: 'SD' },
{ country: 'Syria', code: 'SY' },
{ country: 'Venezuela', code: 'VE' },
{ country: 'Yemen', code: 'YE' },
{ country: 'Zimbabwe', code: 'ZW' },
{ country: 'United States', code: 'US' },
]
const SANCTIONED_COUNTRY_CODES = SANCTIONED_COUNTRIES.map(({ code }) => code)
export default function useIpAddress() {
const [ipAllowed, setIpAllowed] = useState(true)
useEffect(() => {
const checkIpLocation = async () => {
let ipCountryCode
try {
const response = await fetch(`https://www.cloudflare.com/cdn-cgi/trace`)
const parsedResponse = await response.text()
const ipLocation = parsedResponse.match(/loc=(.+)/)
ipCountryCode = ipLocation ? ipLocation[1] : ''
} catch {
const response = await fetch(`https://countrycode.bonfida.workers.dev/`)
const parsedResponse = await response.json()
ipCountryCode = parsedResponse.countryCode
}
if (ipCountryCode) {
setIpAllowed(!SANCTIONED_COUNTRY_CODES.includes(ipCountryCode))
}
}
checkIpLocation()
}, [])
return { ipAllowed }
}

View File

@ -1,41 +0,0 @@
// import useWalletStore from '../stores/useWalletStore'
import { calculateBalance } from '../utils/balance'
import { TokenProgramAccount, TokenAccount } from '../utils/tokens'
export function findLargestBalanceAccountForMint(
mints,
tokenAccounts: TokenProgramAccount<TokenAccount>[],
mintPk
) {
const accounts = tokenAccounts.filter((a) => a.account.mint.equals(mintPk))
if (!accounts.length) return undefined
const balances = accounts.map((a) => calculateBalance(mints, a.account))
const maxBalanceAccountIndex = balances.reduce(
(iMax, bal, iBal) => (bal > balances[iMax] ? iBal : iMax),
0
)
const account = accounts[maxBalanceAccountIndex]
const balance = balances[maxBalanceAccountIndex]
return { account, balance }
}
/*
export default function useLargestAccounts() {
const { pool, tokenAccounts, mints, usdcVault } = useWalletStore(
(state) => state
)
const usdc = usdcVault
? findLargestBalanceAccountForMint(mints, tokenAccounts, usdcVault.mint)
: undefined
const redeemable = pool
? findLargestBalanceAccountForMint(
mints,
tokenAccounts,
pool.redeemableMint
)
: undefined
return { usdc, redeemable }
}
*/

View File

@ -2,7 +2,7 @@ import { useMemo, useState, useEffect, useCallback } from 'react'
const localStorageListeners = {}
export function useLocalStorageStringState(
function useLocalStorageStringState(
key: string,
defaultState: string | null = null
): [string | null, (newState: string | null) => void] {

View File

@ -13,7 +13,7 @@ import {
import useRpcContext from '@hooks/useRpcContext'
import { getVoteRecords, getTokenOwnerRecords } from '@models/proposal'
import useRealm from '@hooks/useRealm'
import { buildTopVoters, VoteType } from '@models/proposal'
import { buildTopVoters } from '@models/proposal'
import useVotePluginsClientStore from 'stores/useVotePluginsClientStore'
import { getLockTokensVotingPowerPerWallet } from 'VoteStakeRegistry/tools/deposits'
import { BN } from '@coral-xyz/anchor'
@ -21,8 +21,6 @@ import useWalletStore from 'stores/useWalletStore'
import useGovernanceAssetsStore from 'stores/useGovernanceAssetsStore'
import { PublicKey } from '@solana/web3.js'
export { VoteType }
export default function useVoteRecords(proposal?: ProgramAccount<Proposal>) {
const { getRpcContext } = useRpcContext()
const [voteRecords, setVoteRecords] = useState<ProgramAccount<VoteRecord>[]>(

View File

@ -554,7 +554,7 @@ export class SimpleGatedVoterWeight implements VoterWeightInterface {
}
/** Returns max VoteWeight for given mint and max source */
export function getMintMaxVoteWeight(
function getMintMaxVoteWeight(
mint: MintInfo,
maxVoteWeightSource: MintMaxVoteWeightSource
) {

View File

@ -1,34 +0,0 @@
import {
Connection,
Keypair,
PublicKey,
TransactionInstruction,
} from '@solana/web3.js'
import * as serum from '@project-serum/common'
import { WalletSigner } from '@solana/spl-governance'
export const withCreateSplTokenAccount = async (
connection: Connection,
wallet: WalletSigner | undefined,
instructions: TransactionInstruction[],
signers: Keypair[],
mint: PublicKey
): Promise<{ tokenAccountAddress: PublicKey }> => {
const tokenAccount = new Keypair()
const provider = new serum.Provider(
connection,
wallet as serum.Wallet,
serum.Provider.defaultOptions()
)
instructions.push(
...(await serum.createTokenAccountInstrs(
provider,
tokenAccount.publicKey,
mint,
wallet!.publicKey!
))
)
signers.push(tokenAccount)
return { tokenAccountAddress: tokenAccount.publicKey }
}

View File

@ -142,7 +142,6 @@
"next-themes": "0.1.1",
"next-transpile-modules": "9.1.0",
"node-fetch": "2.6.7",
"numbro": "2.3.6",
"papaparse": "5.3.2",
"promptly": "3.2.0",
"psyfi-euros-test": "0.0.1-rc.33",

View File

@ -5,7 +5,7 @@ import useProposal from 'hooks/useProposal'
import ProposalStateBadge from '@components/ProposalStateBadge'
import { InstructionPanel } from 'components/instructions/instructionPanel'
import DiscussionPanel from 'components/chat/DiscussionPanel'
import VotePanel from '@components/VotePanel/VotePanel'
import VotePanel from '@components/VotePanel'
import { ApprovalProgress, VetoProgress } from '@components/QuorumProgress'
import useRealm from 'hooks/useRealm'
import useProposalVotes from 'hooks/useProposalVotes'

View File

@ -1,144 +0,0 @@
import { PublicKey } from '@solana/web3.js'
import { SanitizedObject } from 'utils/helpers'
import * as bs58 from 'bs58'
import {
getGovernanceSchemaForAccount,
GovernanceAccount,
GovernanceAccountClass,
GovernanceAccountType,
Realm,
} from '@solana/spl-governance'
import { ProgramAccount } from '@solana/spl-governance'
import { MemcmpFilter, RpcContext } from '@solana/spl-governance'
import { deserializeBorsh } from 'utils/borsh'
import { sleep } from '@project-serum/common'
const fetch = require('node-fetch')
export async function getRealms(rpcContext: RpcContext) {
return getGovernanceAccounts<Realm>(
rpcContext.programId,
rpcContext.endpoint,
Realm,
[GovernanceAccountType.RealmV1, GovernanceAccountType.RealmV2]
)
}
export async function getGovernanceAccounts<TAccount extends GovernanceAccount>(
programId: PublicKey,
endpoint: string,
accountClass: GovernanceAccountClass,
accountTypes: GovernanceAccountType[],
filters: MemcmpFilter[] = []
) {
if (accountTypes.length === 1) {
return getGovernanceAccountsImpl<TAccount>(
programId,
endpoint,
accountClass,
accountTypes[0],
filters
)
}
let accounts: Record<string, ProgramAccount<TAccount>> = {}
for (const at of accountTypes) {
accounts = {
...accounts,
...(await getGovernanceAccountsImpl(
programId,
endpoint,
accountClass,
at,
filters
)),
}
// note: if we are not using a specific RPC, then most probably we are using a public RPC
// sleep to prevent public RPC rate limits
if (!process.env.CLUSTER_URL) {
await sleep(3_000)
}
}
return accounts
}
async function getGovernanceAccountsImpl<TAccount extends GovernanceAccount>(
programId: PublicKey,
endpoint: string,
accountClass: GovernanceAccountClass,
accountType: GovernanceAccountType,
filters: MemcmpFilter[] = []
) {
const getProgramAccounts = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'getProgramAccounts',
params: [
programId.toBase58(),
{
commitment: 'single',
encoding: 'base64',
filters: [
{
memcmp: {
offset: 0,
bytes: bs58.encode([accountType]),
},
},
...filters.map((f) => ({
memcmp: { offset: f.offset, bytes: bs58.encode(f.bytes) },
})),
],
},
],
}),
})
const accounts: Record<
string,
ProgramAccount<TAccount>
> = new SanitizedObject({}) as Record<string, ProgramAccount<TAccount>>
try {
const response = await getProgramAccounts.json()
if ('result' in response) {
const rawAccounts = response['result']
for (const rawAccount of rawAccounts) {
const accountSchema = getGovernanceSchemaForAccount(
rawAccount.account.data[0][0]
)
try {
const account = new SanitizedObject({
pubkey: new PublicKey(rawAccount.pubkey),
account: new SanitizedObject({
...rawAccount.account,
data: [], // There is no need to keep the raw data around once we deserialize it into TAccount
}),
info: deserializeBorsh(
accountSchema,
accountClass,
Buffer.from(rawAccount.account.data[0], 'base64')
),
}) as ProgramAccount<TAccount>
accounts[account.pubkey.toBase58()] = account
} catch (ex) {
console.error(`Can't deserialize ${accountClass}`, ex)
}
}
} else {
console.error(`Unexpected response ${JSON.stringify(response)}`)
}
} catch (e) {
console.error(e)
}
return accounts
}

View File

@ -78,27 +78,27 @@ export type VestAccountType = {
gsrmBurned: anchor.BN
}
export const DEV_PROGRAM_ID = new PublicKey(
const DEV_PROGRAM_ID = new PublicKey(
'EDV6BNBY6pLb4aCJCc5LnELdA9xTywnDZ2m3cWfCbpwZ'
)
export const MAIN_PROGRAM_ID = new PublicKey(
const MAIN_PROGRAM_ID = new PublicKey(
'FBcTbv5rLy7MQkkAU2uDzAEjjZDeu2BVLVRJGxyz6hnV'
)
export const DEV_SRM_MINT = new PublicKey(
const DEV_SRM_MINT = new PublicKey(
'2xKASju8WCUK6zC54TP4h6WhHdqdcWMNoFpqAdvXvHV6'
)
export const DEV_MSRM_MINT = new PublicKey(
const DEV_MSRM_MINT = new PublicKey(
'BoFBTKtdMXC4YALXtNV5tmw1xNWtjxTrR17PvZGmKhmP'
)
export const MAIN_SRM_MINT = new PublicKey(
const MAIN_SRM_MINT = new PublicKey(
'SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt'
)
export const MAIN_MSRM_MINT = new PublicKey(
const MAIN_MSRM_MINT = new PublicKey(
'MSRMcoVyrFxnSgo5uXwone5SKcGhT1KEJMFEkMEWf9L'
)
export const [DEV_GSRM_MINT] = findProgramAddressSync(
const [DEV_GSRM_MINT] = findProgramAddressSync(
[Buffer.from('gSRM')],
DEV_PROGRAM_ID
)

View File

@ -1,27 +1,8 @@
export function mapEntries(xs: any, mapFn: (kv: [string, any]) => any) {
return Object.entries(xs).map(mapFn)
}
export function mapFromEntries(
xs: any,
mapFn: (kv: [string, any]) => [string, any]
) {
return Object.fromEntries(mapEntries(xs, mapFn))
}
// Converts array of items to a Map
export function arrayToMap<T, K>(source: readonly T[], getKey: (item: T) => K) {
return new Map(source.map((item) => [getKey(item), item] as [K, T]))
}
// Returns unique elements from the given source array and using the provided key selector
export function arrayToUnique<T, K>(
source: readonly T[],
getKey: (item: T) => K
) {
return Array.from(arrayToMap(source, getKey).values())
}
export function arrayToRecord<T>(
source: readonly T[],
getKey: (item: T) => string

View File

@ -4,16 +4,3 @@ export function equalsIgnoreCase(
) {
return str1?.toUpperCase() === str2?.toUpperCase()
}
export function endsWithIgnoreCase(string: string, searchString: string) {
return string.toUpperCase().endsWith(searchString.toUpperCase())
}
export function replaceIgnoreCase(
string: string,
searchString: string,
replaceValue: string
) {
const pattern = new RegExp(searchString, 'gi')
return string.replace(pattern, replaceValue)
}

View File

@ -66,7 +66,7 @@ export function createGovernanceThresholds(
}
}
export function createDefaultRealmConfigAccount(realmPk: PublicKey) {
function createDefaultRealmConfigAccount(realmPk: PublicKey) {
const defaultTokenConfig = new GoverningTokenConfig({
voterWeightAddin: undefined,
maxVoterWeightAddin: undefined,

View File

@ -43,7 +43,7 @@ export interface Web3Context {
connection: Connection
wallet: WalletSigner
}
export interface RealmCreationV2 {
interface RealmCreationV2 {
_programVersion: 2
programIdAddress: string

View File

@ -59,7 +59,7 @@ export function fmtTokenInfoWithMint(
export function getMintDecimalAmount(mint: MintInfo, mintAmount: BN) {
return new BigNumber(mintAmount.toString()).shiftedBy(-mint.decimals)
}
export function getBigNumberAmount(amount: BN | number) {
function getBigNumberAmount(amount: BN | number) {
return typeof amount === 'number'
? new BigNumber(amount)
: new BigNumber(amount.toString())
@ -135,7 +135,8 @@ export function getMintSupplyAsDecimal(mint: MintInfo) {
}
// Calculates percentage (provided as 0-100) of mint supply as BigNumber amount
export function getMintSupplyPercentageAsBigNumber(
/** @deprecated why? why would you use a BigNumber for the range 0-100 */
function getMintSupplyPercentageAsBigNumber(
mint: MintInfo,
percentage: number
) {
@ -152,18 +153,6 @@ export function getMintSupplyPercentageAsDecimal(
return getMintSupplyPercentageAsBigNumber(mint, percentage).toNumber()
}
// Calculates percentage (provided as 0-100) of mint supply as rounded BN amount
export function getMintSupplyPercentageAsBN(
mint: MintInfo,
percentage: number
) {
return new BN(
getMintSupplyPercentageAsBigNumber(mint, percentage)
.dp(0, BigNumber.ROUND_DOWN) // BN doesn't support floating point and we have to round it
.toString()
)
}
// Formats percentage value showing it in human readable form
export function fmtPercentage(percentage: number) {
if (percentage === 0 || percentage === Infinity) {

View File

@ -36,7 +36,7 @@ import useWalletOnePointOh from '@hooks/useWalletOnePointOh'
type EmptyObject = Record<string, never>
type SetFormErrors = Dispatch<React.SetStateAction<EmptyObject>>
export function getFilteredTokenAccounts(): AssetAccount[] {
function getFilteredTokenAccounts(): AssetAccount[] {
// eslint-disable-next-line react-hooks/rules-of-hooks -- TODO this is potentially quite serious! please fix next time the file is edited, -@asktree
const { governedTokenAccountsWithoutNfts } = useGovernanceAssets()
return governedTokenAccountsWithoutNfts.filter((x) => {
@ -249,7 +249,7 @@ function ForesightUseEffects<T extends ForesightHasGovernedAccount>(
}, [form])
}
export function getSchema<T extends ForesightHasGovernedAccount>(
function getSchema<T extends ForesightHasGovernedAccount>(
extraFields: {
[name in keyof Omit<T, 'governedAccount'>]: StringSchema | NumberSchema
}

View File

@ -20,7 +20,7 @@ import axios from 'axios'
import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes'
import { PublicKey } from '@solana/web3.js'
export interface GovernanceConfigValues {
interface GovernanceConfigValues {
minTokensToCreateProposal: number | string
minInstructionHoldUpTime: number
maxVotingTime: number
@ -32,10 +32,7 @@ export interface GovernanceConfigValues {
}
// Parses min tokens to create (proposal or governance)
export function parseMinTokensToCreate(
value: string | number,
mintDecimals: number
) {
function parseMinTokensToCreate(value: string | number, mintDecimals: number) {
return typeof value === 'string'
? parseMintNaturalAmountFromDecimal(value, mintDecimals)
: getMintNaturalAmountFromDecimal(value, mintDecimals)

View File

@ -1,36 +0,0 @@
import { PublicKey } from '@solana/web3.js'
import BN from 'bn.js'
import { MintAccount, TokenAccount } from './tokens'
function fixedPointToNumber(value: BN, decimals: number) {
const divisor = new BN(10).pow(new BN(decimals))
const quotient = value.div(divisor)
const remainder = value.mod(divisor)
return quotient.toNumber() + remainder.toNumber() / divisor.toNumber()
}
export function calculateBalance(
mints: { [pk: string]: MintAccount },
account: TokenAccount
): number {
const mint = mints[account.mint.toBase58()]
return mint ? fixedPointToNumber(account.amount, mint.decimals) : 0
}
export function calculateSupply(
mints: { [pk: string]: MintAccount },
pk: PublicKey
): number | undefined {
const mint = mints[pk.toBase58()]
return mint && fixedPointToNumber(mint.supply, mint.decimals)
}
export function calculateNativeAmountUnsafe(
mints: { [pk: string]: MintAccount },
pk: PublicKey,
amount: number
): BN {
const mint = mints[pk.toBase58()]
const nativeAmount = Math.round(amount * Math.pow(10, mint.decimals))
return new BN(nativeAmount.toString())
}

View File

@ -1,55 +0,0 @@
import { MintInfo, MintLayout, u64 } from '@solana/spl-token'
import { AccountInfo, Connection, PublicKey } from '@solana/web3.js'
/**
* Returns an array with arrays of the given size.
*
* @param myArray {Array} Array to split
* @param chunkSize {Integer} Size of every group
*/
const chunkArray = <T>(myArray: T[], chunkSize: number) => {
let index = 0
const arrayLength = myArray.length
const tempArray: T[][] = []
for (index = 0; index < arrayLength; index += chunkSize) {
const myChunk = myArray.slice(index, index + chunkSize)
tempArray.push(myChunk)
}
return tempArray
}
const batchLoadMints = async (connection: Connection, mints: PublicKey[]) => {
const groupOfMints: PublicKey[][] = chunkArray(mints, 100)
const getMultipleAccountsInfoPromises: Promise<
(AccountInfo<Buffer> | null)[]
>[] = groupOfMints.map((mints) => {
return connection.getMultipleAccountsInfo(mints)
})
const results = await Promise.all(getMultipleAccountsInfoPromises)
const infos: (AccountInfo<Buffer> | null)[] = results.flat()
const mintInfos: Record<string, MintInfo> = {}
infos.forEach((info, index) => {
if (!info) return
const mintInfo = MintLayout.decode(info.data)
if (mintInfo.mintAuthorityOption === 0) {
mintInfo.mintAuthority = null
} else {
mintInfo.mintAuthority = new PublicKey(mintInfo.mintAuthority)
}
mintInfo.supply = u64.fromBuffer(mintInfo.supply)
mintInfo.isInitialized = mintInfo.isInitialized !== 0
if (mintInfo.freezeAuthorityOption === 0) {
mintInfo.freezeAuthority = null
} else {
mintInfo.freezeAuthority = new PublicKey(mintInfo.freezeAuthority)
}
mintInfos[mints[index].toString()] = mintInfo
})
return mintInfos
}
export default batchLoadMints

View File

@ -3,7 +3,6 @@ import { BN } from '@coral-xyz/anchor'
export const DAYS_PER_YEAR = 365
export const SECS_PER_DAY = 86400
export const DAYS_PER_MONTH = DAYS_PER_YEAR / 12
export const SECS_PER_MONTH = DAYS_PER_MONTH * SECS_PER_DAY
export const HOURS_PER_DAY = 24
export const MINS_PER_HOUR = 60

View File

@ -1,46 +0,0 @@
import { AccountInfo, PublicKey } from '@solana/web3.js'
import { AccountLayout } from '@solana/spl-token'
import { BN } from '@coral-xyz/anchor'
interface TokenAccount {
amount: BN
closeAuthority: PublicKey
closeAuthorityOption: number
delegate: PublicKey
delegateOption: number
delegatedAmount: BN
isNative: number
isNativeOption: number
mint: PublicKey
owner: PublicKey
state: number
}
export interface TokenAccountWithKey extends TokenAccount {
key: PublicKey
}
export const deserializeSplTokenAccount = (
accountInfo: AccountInfo<Buffer>
): TokenAccount => {
const _accountInfo = AccountLayout.decode(accountInfo.data)
const amountBuffer = Buffer.from(_accountInfo.amount)
const amount = new BN(amountBuffer, 'hex', 'le')
const delegatedAmountBuffer = Buffer.from(_accountInfo.delegatedAmount)
const delegatedAmount = new BN(delegatedAmountBuffer, 'hex', 'le')
const isNativeBuffer = Buffer.from(_accountInfo.isNative)
const isNative = isNativeBuffer.readUIntLE(0, 8)
return {
amount,
closeAuthority: new PublicKey(_accountInfo.closeAuthority),
closeAuthorityOption: _accountInfo.closeAuthority,
delegate: new PublicKey(_accountInfo.delegate),
delegateOption: _accountInfo.delegateOption,
delegatedAmount,
isNative,
isNativeOption: _accountInfo.isNativeOption,
mint: new PublicKey(_accountInfo.mint),
owner: new PublicKey(_accountInfo.owner),
state: _accountInfo.state,
}
}

View File

@ -35,7 +35,7 @@ export function precision(a) {
return p
}
export const fmtMsToTime = (milliseconds: number) => {
const fmtMsToTime = (milliseconds: number) => {
let seconds = Math.floor(milliseconds / 1000)
let minutes = Math.floor(seconds / 60)
let hours = Math.floor(minutes / 60)

View File

@ -1,7 +1,5 @@
import {
getNativeTreasuryAddress,
Governance,
ProgramAccount,
serializeInstructionToBase64,
} from '@solana/spl-governance'
import {
@ -46,89 +44,7 @@ export const validateInstruction = async ({
return isValid
}
export async function getGenericTransferInstruction({
schema,
form,
programId,
connection,
wallet,
setFormErrors,
requiredStateInfo,
}: {
schema: any
form: any
programId: PublicKey | undefined
connection: ConnectionContext
wallet: WalletAdapter | undefined
requiredStateInfo: {
/// The mint that is being transfered
mint: PublicKey
/// The TokenAccount address that will be sending the tokens
tokenSource: PublicKey
/// The number of decimals for this token's mint
mintDecimals: number
/// The governance that controls this account
governance: ProgramAccount<Governance>
/// The key that has to sign for the token transfer
owner: PublicKey
}
setFormErrors: any
}): Promise<UiInstruction> {
const isValid = await validateInstruction({ schema, form, setFormErrors })
let serializedInstruction = ''
const prerequisiteInstructions: TransactionInstruction[] = []
if (isValid && programId) {
const sourceAccount = requiredStateInfo.tokenSource
//this is the original owner
const destinationAccount = new PublicKey(form.destinationAccount)
const mintPK = requiredStateInfo.mint
const mintAmount = parseMintNaturalAmountFromDecimal(
form.amount!,
requiredStateInfo.mintDecimals
)
//we find true receiver address if its wallet and we need to create ATA the ata address will be the receiver
const { currentAddress: receiverAddress, needToCreateAta } = await getATA({
connection: connection,
receiverAddress: destinationAccount,
mintPK,
wallet: wallet!,
})
//we push this createATA instruction to transactions to create right before creating proposal
//we don't want to create ata only when instruction is serialized
if (needToCreateAta) {
prerequisiteInstructions.push(
Token.createAssociatedTokenAccountInstruction(
ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID
TOKEN_PROGRAM_ID, // always TOKEN_PROGRAM_ID
mintPK, // mint
receiverAddress, // ata
destinationAccount, // owner of token account
wallet!.publicKey! // fee payer
)
)
}
const transferIx = Token.createTransferInstruction(
TOKEN_PROGRAM_ID,
sourceAccount,
receiverAddress,
requiredStateInfo.owner,
[],
new u64(mintAmount.toString())
)
serializedInstruction = serializeInstructionToBase64(transferIx)
}
const obj: UiInstruction = {
serializedInstruction,
isValid,
governance: requiredStateInfo.governance,
prerequisiteInstructions: prerequisiteInstructions,
}
return obj
}
/** @deprecated */
export async function getTransferInstruction({
schema,
form,

View File

@ -6,7 +6,6 @@ import {
TransactionInstruction,
} from '@solana/web3.js'
import BN from 'bn.js'
import { deserializeUnchecked } from 'borsh'
import * as BufferLayout from 'buffer-layout'
const calculateReserveAccount = async (lidoAddress, programId) => {
@ -25,270 +24,6 @@ const calculateMintAuthority = async (lidoAddress, programId) => {
return mint[0]
}
export const getAccountInfo = async (connection, lidoAddress) => {
class Lido {
constructor(data) {
Object.assign(this, data)
}
}
class SeedRange {
constructor(data) {
Object.assign(this, data)
}
}
class Validator {
constructor(data) {
Object.assign(this, data)
}
}
class PubKeyAndEntry {
constructor(data) {
Object.assign(this, data)
}
}
class PubKeyAndEntryMaintainer {
constructor(data) {
Object.assign(this, data)
}
}
class RewardDistribution {
constructor(data) {
Object.assign(this, data)
}
}
class FeeRecipients {
constructor(data) {
Object.assign(this, data)
}
}
class Validators {
constructor(data) {
Object.assign(this, data)
}
}
class Maintainers {
constructor(data) {
Object.assign(this, data)
}
}
class ExchangeRate {
constructor(data) {
Object.assign(this, data)
}
}
class Metrics {
constructor(data) {
Object.assign(this, data)
}
}
class LamportsHistogram {
constructor(data) {
Object.assign(this, data)
}
}
class WithdrawMetric {
constructor(data) {
Object.assign(this, data)
}
}
const schema = new Map([
[
ExchangeRate,
{
kind: 'struct',
fields: [
['computed_in_epoch', 'u64'],
['st_sol_supply', 'u64'],
['sol_balance', 'u64'],
],
},
],
[
LamportsHistogram,
{
kind: 'struct',
fields: [
['counts1', 'u64'],
['counts2', 'u64'],
['counts3', 'u64'],
['counts4', 'u64'],
['counts5', 'u64'],
['counts6', 'u64'],
['counts7', 'u64'],
['counts8', 'u64'],
['counts9', 'u64'],
['counts10', 'u64'],
['counts11', 'u64'],
['counts12', 'u64'],
['total', 'u64'],
],
},
],
[
WithdrawMetric,
{
kind: 'struct',
fields: [
['total_st_sol_amount', 'u64'],
['total_sol_amount', 'u64'],
['count', 'u64'],
],
},
],
[
Metrics,
{
kind: 'struct',
fields: [
['fee_treasury_sol_total', 'u64'],
['fee_validation_sol_total', 'u64'],
['fee_developer_sol_total', 'u64'],
['st_sol_appreciation_sol_total', 'u64'],
['fee_treasury_st_sol_total', 'u64'],
['fee_validation_st_sol_total', 'u64'],
['fee_developer_st_sol_total', 'u64'],
['deposit_amount', LamportsHistogram],
['withdraw_amount', WithdrawMetric],
],
},
],
[
SeedRange,
{
kind: 'struct',
fields: [
['begin', 'u64'],
['end', 'u64'],
],
},
],
[
Validator,
{
kind: 'struct',
fields: [
['fee_credit', 'u64'],
['fee_address', 'u256'],
['stake_seeds', SeedRange],
['unstake_seeds', SeedRange],
['stake_accounts_balance', 'u64'],
['unstake_accounts_balance', 'u64'],
['active', 'u8'],
],
},
],
[
PubKeyAndEntry,
{
kind: 'struct',
fields: [
['pubkey', 'u256'],
['entry', Validator],
],
},
],
[
PubKeyAndEntryMaintainer,
{
kind: 'struct',
fields: [
['pubkey', 'u256'],
['entry', [0]],
],
},
],
[
RewardDistribution,
{
kind: 'struct',
fields: [
['treasury_fee', 'u32'],
['validation_fee', 'u32'],
['developer_fee', 'u32'],
['st_sol_appreciation', 'u32'],
],
},
],
[
FeeRecipients,
{
kind: 'struct',
fields: [
['treasury_account', 'u256'],
['developer_account', 'u256'],
],
},
],
[
Validators,
{
kind: 'struct',
fields: [
['entries', [PubKeyAndEntry]],
['maximum_entries', 'u32'],
],
},
],
[
Maintainers,
{
kind: 'struct',
fields: [
['entries', [PubKeyAndEntryMaintainer]],
['maximum_entries', 'u32'],
],
},
],
[
Lido,
{
kind: 'struct',
fields: [
['lido_version', 'u8'],
['manager', 'u256'],
['st_sol_mint', 'u256'],
['exchange_rate', ExchangeRate],
['sol_reserve_authority_bump_seed', 'u8'],
['stake_authority_bump_seed', 'u8'],
['mint_authority_bump_seed', 'u8'],
['rewards_withdraw_authority_bump_seed', 'u8'],
['reward_distribution', RewardDistribution],
['fee_recipients', FeeRecipients],
['metrics', Metrics],
['validators', Validators],
['maintainers', Maintainers],
],
},
],
])
const accountInfo = await connection.getAccountInfo(lidoAddress)
return deserializeUnchecked(schema, Lido, accountInfo.data)
}
const getDepositKeys = async (
payer,
recipient,

View File

@ -45,7 +45,7 @@ export const compareProposals = (
return p1.getStateTimestamp() - p2.getStateTimestamp()
}
export function getVotingStateRank(
function getVotingStateRank(
proposal: Proposal,
governances: {
[governance: string]: ProgramAccount<Governance>

View File

@ -18,7 +18,7 @@ class TransactionError extends Error {
}
}
export function getUnixTs() {
function getUnixTs() {
return new Date().getTime() / 1000
}

View File

@ -1,16 +1,5 @@
import * as Sentry from '@sentry/react'
import { SignerWalletAdapter } from '@solana/wallet-adapter-base'
import {
Commitment,
Connection,
RpcResponseAndContext,
SignatureStatus,
SimulatedTransactionResponse,
Transaction,
TransactionInstruction,
TransactionSignature,
Keypair,
} from '@solana/web3.js'
import { TransactionInstruction, Keypair } from '@solana/web3.js'
import {
closeTransactionProcessUi,
incrementProcessedTransactions,
@ -22,27 +11,6 @@ import {
sendSignAndConfirmTransactionsProps,
} from '@blockworks-foundation/mangolana/lib/transactions'
interface TransactionInstructionWithType {
instructionsSet: TransactionInstruction[]
sequenceType?: SequenceType
}
interface TransactionsPlayingIndexes {
transactionsIdx: { [txIdx: number]: number }[]
sequenceType?: SequenceType
}
interface Block {
blockhash: string
lastValidBlockHeight: number
}
// TODO: sendTransactions() was imported from Oyster as is and needs to be reviewed and updated
// In particular common primitives should be unified with send.tsx and also ensure the same resiliency mechanism
// is used for monitoring transactions status and timeouts
const sleep = (ttl: number) =>
new Promise((resolve) => setTimeout(() => resolve(true), ttl))
export type WalletSigner = Pick<
SignerWalletAdapter,
'publicKey' | 'signTransaction' | 'signAllTransactions'
@ -56,474 +24,12 @@ export function getWalletPublicKey(wallet: WalletSigner) {
return wallet.publicKey
}
async function awaitTransactionSignatureConfirmation(
txid: TransactionSignature,
//after that time we will start to check blockHeight
startTimeoutCheckThreshold: number,
connection: Connection,
commitment: Commitment = 'recent',
queryStatus = false,
startingBlock: Block
) {
//If the validator cant find a slot number for the blockhash
//or if the looked up slot number is more than 151 slots lower
// than the slot number of the block being processed, the transaction will be rejected.
const timeoutBlockPeriod = 152
const timeoutBlockHeight =
startingBlock.lastValidBlockHeight + timeoutBlockPeriod
console.log('Start block height', startingBlock?.lastValidBlockHeight)
console.log('Possible timeout block', timeoutBlockHeight)
let done = false
let startTimeoutCheck = false
let timeout = false
let status: SignatureStatus | null = {
slot: 0,
confirmations: 0,
err: null,
}
let subId = 0
await new Promise((resolve, reject) => {
const fn = async () => {
setTimeout(() => {
if (done) {
return
}
console.log('Starting timeout check')
console.log(
'Timeout check was set to start after',
startTimeoutCheckThreshold
)
startTimeoutCheck = true
}, startTimeoutCheckThreshold)
try {
subId = connection.onSignature(
txid,
(result, context) => {
done = true
status = {
err: result.err,
slot: context.slot,
confirmations: 0,
}
if (result.err) {
console.log('Rejected via websocket', result.err)
Sentry.captureException(
`awaitTransactionSignatureConfirmation line 107: ${result.err}`,
{ tags: { tag: 'sendTransactionsErrors' } }
)
reject(result.err)
} else {
console.log('Resolved via websocket', result)
resolve(result)
}
},
commitment
)
} catch (e) {
done = true
console.error('WS error in setup', txid, e)
}
while (!done && queryStatus) {
// eslint-disable-next-line no-loop-func
const fn = async () => {
try {
const promises: [
Promise<RpcResponseAndContext<(SignatureStatus | null)[]>>,
Promise<number>?
] = [connection.getSignatureStatuses([txid])]
//if startTimeoutThreshold passed we start to check if
//current blocks are did not passed timeoutBlockHeight threshold
if (startTimeoutCheck) {
promises.push(connection.getBlockHeight('confirmed'))
}
const [signatureStatuses, blockHeight] = await Promise.all(promises)
if (
typeof blockHeight !== undefined &&
timeoutBlockHeight <= blockHeight!
) {
done = true
timeout = true
console.log('Tx Timeout ----')
reject({ timeout: true })
}
if (blockHeight) {
console.log('Timeout threshold blockheight', timeoutBlockHeight)
console.log('Current blockheight', blockHeight)
}
status = signatureStatuses && signatureStatuses.value[0]
if (!done) {
if (!status) {
console.log('REST null result for', txid, status)
} else if (status.err) {
console.log('REST error for', txid, status)
done = true
Sentry.captureException(
`awaitTransactionSignatureConfirmation line 158: ${status.err}`,
{ tags: { tag: 'sendTransactionsErrors' } }
)
reject(status.err)
} else if (!status.confirmations) {
console.log('REST no confirmations for', txid, status)
} else {
console.log('REST confirmation for', txid, status)
done = true
resolve(status)
}
}
} catch (e) {
if (!done) {
Sentry.captureException(
`awaitTransactionSignatureConfirmation line 173: ${e}`,
{ tags: { tag: 'sendTransactionsErrors' } }
)
console.log('REST connection error: txid', txid, e)
}
}
}
fn()
await sleep(2000)
}
}
fn()
})
.catch(() => {
//@ts-ignore
if (connection._signatureSubscriptions[subId])
connection.removeSignatureListener(subId)
})
.then((_) => {
//@ts-ignore
if (connection._signatureSubscriptions[subId])
connection.removeSignatureListener(subId)
})
done = true
return { status, timeout }
}
///////////////////////////////////////
export const getUnixTs = () => {
return new Date().getTime() / 1000
}
const DEFAULT_TIMEOUT = 60000
/////////////////////////////////////////////////
export async function sendSignedTransaction({
signedTransaction,
connection,
timeout = DEFAULT_TIMEOUT,
block,
transactionInstructionIdx,
showUiComponent = false,
}: {
signedTransaction: Transaction
connection: Connection
sendingMessage?: string
sentMessage?: string
successMessage?: string
timeout?: number
block: Block
transactionInstructionIdx?: number
showUiComponent?: boolean
}): Promise<{ txid: string; slot: number }> {
const rawTransaction = signedTransaction.serialize()
const startTime = getUnixTs()
let slot = 0
const txid: TransactionSignature = await connection.sendRawTransaction(
rawTransaction,
{
skipPreflight: true,
}
)
console.log('Started awaiting confirmation for', txid)
let hasTimeout = false
let done = false
;(async () => {
while (!done && getUnixTs() - startTime < timeout) {
connection.sendRawTransaction(rawTransaction, {
skipPreflight: true,
})
await sleep(500)
}
})()
try {
const confirmation = await awaitTransactionSignatureConfirmation(
txid,
timeout,
connection,
'recent',
true,
block
)
if (confirmation?.status?.err) {
throw new Error('Transaction failed: Custom instruction error')
}
slot = confirmation?.status?.slot || 0
hasTimeout = confirmation.timeout
} catch (err) {
Sentry.captureException(`sendSignedTransaction line 287: ${err}`, {
tags: { tag: 'sendTransactionsErrors' },
})
let simulateResult: SimulatedTransactionResponse | null = null
try {
simulateResult = (await connection.simulateTransaction(signedTransaction))
.value
} catch (e) {
//
}
if (simulateResult && simulateResult.err) {
if (simulateResult.logs) {
for (let i = simulateResult.logs.length - 1; i >= 0; --i) {
const line = simulateResult.logs[i]
if (line.startsWith('Program log: ')) {
Sentry.captureException(`sendSignedTransaction line 303: ${line}`)
throw {
txInstructionIdx: transactionInstructionIdx,
error:
'Transaction failed: ' + line.slice('Program log: '.length),
txid: txid,
}
}
}
}
Sentry.captureException(
`sendSignedTransaction line 314: ${simulateResult.err}`,
{ tags: { tag: 'sendTransactionsErrors' } }
)
throw {
txInstructionIdx: transactionInstructionIdx,
error: JSON.stringify(simulateResult.err),
txid: txid,
}
}
// throw new Error('Transaction failed');
} finally {
done = true
}
if (hasTimeout) {
throw {
txInstructionIdx: transactionInstructionIdx,
error: 'Timed out awaiting confirmation on transaction',
txid: txid,
}
}
if (showUiComponent) {
incrementProcessedTransactions()
}
console.log('Latency', txid, getUnixTs() - startTime)
return { txid, slot }
}
export enum SequenceType {
Sequential,
Parallel,
StopOnFailure,
}
/**
* @deprecated The method should not be used use sendTransactionsV3
*/
/////////////////////////////////////////
export const sendTransactionsV2 = async ({
connection,
wallet,
TransactionInstructions,
signersSet,
block,
showUiComponent = false,
runAfterApproval,
runAfterTransactionConfirmation,
}: {
connection: Connection
wallet: WalletSigner
TransactionInstructions: TransactionInstructionWithType[]
signersSet: Keypair[][]
block?: Block
showUiComponent?: boolean
runAfterApproval?: (() => void) | null
runAfterTransactionConfirmation?: (() => void) | null
}) => {
if (!wallet.publicKey) throw new Error('Wallet not connected!')
//block will be used for timeout calculation
if (!block) {
block = await connection.getLatestBlockhash('confirmed')
}
const maxTransactionsInBath =
TransactionInstructions.filter(
(x) => x.sequenceType === SequenceType.Sequential
).length > 0
? 20
: 30
const currentTransactions = TransactionInstructions.slice(
0,
maxTransactionsInBath
)
const unsignedTxns: Transaction[] = []
//this object will determine how we run transactions e.g [ParallelTx, SequenceTx, ParallelTx]
const transactionCallOrchestrator: TransactionsPlayingIndexes[] = []
for (let i = 0; i < currentTransactions.length; i++) {
const transactionInstruction = currentTransactions[i]
const signers = signersSet[i]
if (transactionInstruction.instructionsSet.length === 0) {
continue
}
const transaction = new Transaction({ feePayer: wallet.publicKey })
transactionInstruction.instructionsSet.forEach((instruction) =>
transaction.add(instruction)
)
transaction.recentBlockhash = block.blockhash
if (signers.length > 0) {
transaction.partialSign(...signers)
}
//we take last index of unsignedTransactions to have right indexes because
//if transactions was empty
//then unsigned transactions could not mach TransactionInstructions param indexes
const currentUnsignedTxIdx = unsignedTxns.length
const currentTransactionCall =
transactionCallOrchestrator[transactionCallOrchestrator.length - 1]
//we check if last item in current transactions call type is same
//if not then we create next transaction type
if (
currentTransactionCall &&
currentTransactionCall.sequenceType ===
transactionInstruction.sequenceType
) {
//we push reflection of transactionInstruction as object value for retry.
currentTransactionCall.transactionsIdx.push({ [currentUnsignedTxIdx]: i })
} else {
transactionCallOrchestrator.push({
//we push reflection of transactionInstruction as object value for retry.
transactionsIdx: [{ [currentUnsignedTxIdx]: i }],
sequenceType: transactionInstruction.sequenceType,
})
}
unsignedTxns.push(transaction)
}
console.log(transactionCallOrchestrator)
const signedTxns = await wallet.signAllTransactions(unsignedTxns)
if (showUiComponent) {
showTransactionsProcessUi(signedTxns.length)
}
if (runAfterApproval) {
runAfterApproval()
}
console.log(
'Transactions play type order',
transactionCallOrchestrator.map((x) => {
return {
...x,
sequenceType:
typeof x.sequenceType !== 'undefined'
? SequenceType[SequenceType[x.sequenceType]]
: 'Parallel',
}
})
)
console.log('Signed transactions', signedTxns)
try {
for (const fcn of transactionCallOrchestrator) {
if (
typeof fcn.sequenceType === 'undefined' ||
fcn.sequenceType === SequenceType.Parallel
) {
//wait for all Parallel
await Promise.all(
fcn.transactionsIdx.map((idx) => {
const transactionIdx = Object.keys(idx)[0]
const transactionInstructionIdx = idx[transactionIdx]
return sendSignedTransaction({
connection,
signedTransaction: signedTxns[transactionIdx],
block: block!,
transactionInstructionIdx: transactionInstructionIdx,
showUiComponent,
})
})
)
}
if (fcn.sequenceType === SequenceType.Sequential) {
//wait for all Sequential
for (const idx of fcn.transactionsIdx) {
const transactionIdx = Object.keys(idx)[0]
const transactionInstructionIdx = idx[transactionIdx]
await sendSignedTransaction({
connection,
signedTransaction: signedTxns[transactionIdx],
block,
transactionInstructionIdx: transactionInstructionIdx,
showUiComponent,
})
}
}
}
//we call recursively our function to forward rest of transactions if
// number of them is higher then maxTransactionsInBath
if (TransactionInstructions.length > maxTransactionsInBath) {
const forwardedTransactions = TransactionInstructions.slice(
maxTransactionsInBath,
TransactionInstructions.length
)
const forwardedSigners = signersSet.slice(
maxTransactionsInBath,
TransactionInstructions.length
)
await sendTransactionsV2({
connection,
wallet,
TransactionInstructions: forwardedTransactions,
signersSet: forwardedSigners,
showUiComponent,
})
}
if (showUiComponent) {
closeTransactionProcessUi()
}
if (runAfterTransactionConfirmation) {
runAfterTransactionConfirmation()
}
} catch (e) {
if (showUiComponent) {
const idx = e?.txInstructionIdx
const txInstructionForRetry = TransactionInstructions.slice(
idx,
TransactionInstructions.length
)
const signersForRetry = signersSet.slice(idx, signersSet.length)
if (showUiComponent) {
showTransactionError(
() =>
sendTransactionsV2({
connection,
wallet,
TransactionInstructions: txInstructionForRetry,
signersSet: signersForRetry,
showUiComponent,
runAfterApproval: runAfterApproval,
runAfterTransactionConfirmation: runAfterTransactionConfirmation,
}),
e.error ? e.error : `${e}`,
e.txid
)
}
}
throw e
}
}
export const transactionInstructionsToTypedInstructionsSets = (
instructionsSet: TransactionInstruction[],
type: SequenceType
): TransactionInstructionWithType => {
return {
instructionsSet: instructionsSet,
sequenceType: type,
}
}
export const sendTransactionsV3 = ({
connection,
wallet,

View File

@ -17,7 +17,7 @@ export type TokenInfo = {
readonly extensions?: TokenExtensions
}
export interface TokenExtensions {
interface TokenExtensions {
readonly website?: string
readonly bridgeContract?: string
readonly assetContract?: string

View File

@ -3,13 +3,13 @@ import SolendConfiguration, {
SupportedCollateralMintNames as SolendSupportedCollateralMintNames,
} from '@tools/sdk/solend/configuration'
export type SplTokenInformation = {
type SplTokenInformation = {
name: string
mint: PublicKey
decimals: number
}
export type SupportedSplTokenNames =
type SupportedSplTokenNames =
| 'USDC'
| 'WSOL'
| SolendSupportedCollateralMintNames
@ -31,22 +31,3 @@ export const SPL_TOKENS: {
...SolendConfiguration.getSupportedCollateralMintsInformation(),
} as const
export type SplTokenUIName = typeof SPL_TOKENS[keyof typeof SPL_TOKENS]['name']
export function getSplTokenMintAddressByUIName(
nameToMatch: SplTokenUIName
): PublicKey {
const item = Object.entries(SPL_TOKENS).find(
([_, { name }]) => name === nameToMatch
)
// theoretically impossible case
if (!item) {
throw new Error('Unable to find SPL token mint address by UI name')
}
const [, { mint }] = item
return mint
}

View File

@ -1,6 +1,6 @@
import {validatePubkey} from '@utils/formValidation'
import { validatePubkey } from '@utils/formValidation'
export interface Addresses {
interface Addresses {
valid: string[]
invalid: string[]
}

View File

@ -27,7 +27,6 @@ import BigNumber from 'bignumber.js'
import { AssetAccount } from '@utils/uiTypes/assets'
import { NFTWithMeta } from './uiTypes/VotePlugin'
import { ConnectionContext } from './connection'
import { I80F48 } from '@blockworks-foundation/mango-v4'
import {
Metaplex,
Nft,
@ -259,11 +258,6 @@ export async function tryGetMint(
}
}
/** @deprecated -- why? */
export const I80F48OptionalFromNumber = (val: number | undefined) => {
return val || val === 0 ? I80F48.fromNumber(val) : undefined
}
/** @deprecated -- use react-query by pubkey */
export async function tryGetTokenAccount(
connection: Connection,
@ -520,31 +514,6 @@ export type AccountInfoGen<T> = {
rentEpoch?: number
}
export const deserializeMint = (data: Buffer) => {
if (data.length !== MintLayout.span) {
throw new Error('Not a valid Mint')
}
const mintInfo = MintLayout.decode(data)
if (mintInfo.mintAuthorityOption === 0) {
mintInfo.mintAuthority = null
} else {
mintInfo.mintAuthority = new PublicKey(mintInfo.mintAuthority)
}
mintInfo.supply = u64.fromBuffer(mintInfo.supply)
mintInfo.isInitialized = mintInfo.isInitialized !== 0
if (mintInfo.freezeAuthorityOption === 0) {
mintInfo.freezeAuthority = null
} else {
mintInfo.freezeAuthority = new PublicKey(mintInfo.freezeAuthority)
}
return mintInfo as MintInfo
}
/** @deprecated just use react-query by owner pubkey */
export const getNfts = (
ownerPk: PublicKey,
@ -568,7 +537,7 @@ export const parseMintSupplyFraction = (fraction: string) => {
})
}
export const SCALED_FACTOR_SHIFT = 9
const SCALED_FACTOR_SHIFT = 9
export function getScaledFactor(amount: number) {
return new BN(

View File

@ -11,7 +11,7 @@ export interface Member {
delegateWalletCommunity?: PublicKey
}
export interface Delegate {
interface Delegate {
communityMembers?: Array<Member>
councilMembers?: Array<Member>
communityTokenCount?: BN

View File

@ -1,6 +1,5 @@
import { Governance, InstructionData } from '@solana/spl-governance'
import { Governance } from '@solana/spl-governance'
import { ProgramAccount } from '@solana/spl-governance'
import { RpcContext } from '@solana/spl-governance'
import { MintInfo } from '@solana/spl-token'
import { PublicKey, Keypair, TransactionInstruction } from '@solana/web3.js'
import { getNameOf } from '@tools/core/script'
@ -209,23 +208,6 @@ export interface ProgramUpgradeForm {
bufferSpillAddress?: string | undefined
}
export interface CreateStreamForm {
recipient: string
tokenAccount?: AssetAccount
start: string
depositedAmount: number
releaseAmount: number
amountAtCliff: number
cancelable: boolean
period: number
}
export interface CancelStreamForm {
recipient: string
strmMetadata: string
tokenAccount?: AssetAccount
}
export const programUpgradeFormNameOf = getNameOf<ProgramUpgradeForm>()
export interface MangoMakeAddOracleForm {
@ -240,152 +222,6 @@ export type NameValue = {
value: string
}
export interface MangoMakeSetMarketModeForm {
governedAccount: AssetAccount | null
mangoGroup: NameValue | null
marketIndex: NameValue | null
marketMode: NameValue | null
marketType: NameValue | null
adminPk: string
}
export interface MangoSwapSpotMarketForm {
governedAccount: AssetAccount | null
mangoGroup: NameValue | null
market: NameValue | null
adminPk: string
newSpotMarketPk: string
}
export interface MangoRemoveOracleForm {
governedAccount: AssetAccount | null
mangoGroup: NameValue | null
adminPk: string
oraclePk: NameValue | null
}
export interface MangoRemovePerpMarketForm {
governedAccount: AssetAccount | null
mangoGroup: NameValue | null
marketPk: NameValue | null
adminPk: string
mngoDaoVaultPk: string
}
export interface MangoDepositToMangoAccountForm {
governedAccount: AssetAccount | null
amount: number
mangoAccountPk: string
}
export interface MangoDepositToMangoAccountFormCsv {
governedAccount: AssetAccount | null
data: any[]
}
export interface MangoRemoveSpotMarketForm {
governedAccount: AssetAccount | null
mangoGroup: NameValue | null
marketIndex: NameValue | null
adminPk: string
adminVaultPk: string
}
export interface MangoMakeAddSpotMarketForm {
governedAccount: AssetAccount | undefined
programId: string | undefined
mangoGroup: string | undefined
oracleAccount: string | undefined
serumAccount: string | undefined
maintLeverage: number
initLeverage: number
liquidationFee: number
optUtil: number
optRate: number
maxRate: number
}
export interface MangoMakeChangeSpotMarketForm {
governedAccount: AssetAccount | undefined
programId: string | undefined
mangoGroup: string | undefined
baseSymbol: string | undefined
maintLeverage: number | undefined
initLeverage: number | undefined
liquidationFee: number | undefined
optUtil: number
optRate: number
maxRate: number
version: string | undefined
}
export interface MangoMakeChangePerpMarketForm {
governedAccount: AssetAccount | undefined
programId: string | undefined
mangoGroup: string | undefined
perpMarket: string | undefined
mngoPerPeriod: string | undefined
maxDepthBps: string | undefined
lmSizeShift: string | undefined
makerFee: string | undefined
takerFee: string | undefined
maintLeverage: string | undefined
initLeverage: string | undefined
liquidationFee: string | undefined
rate: string | undefined
exp: string | undefined
targetPeriodLength: string | undefined
version: string | undefined
}
export interface MangoMakeCreatePerpMarketForm {
governedAccount: AssetAccount | undefined
programId: string | undefined
mangoGroup: string | undefined
oracleAccount: string | undefined
baseDecimals: number
baseLotSize: number
quoteLotSize: number
mngoPerPeriod: number
maxDepthBps: number
lmSizeShift: number
makerFee: number
takerFee: number
maintLeverage: number
initLeverage: number
liquidationFee: number
rate: number
exp: number
targetPeriodLength: number
version: number
}
export interface MangoMakeChangeMaxAccountsForm {
governedAccount: AssetAccount | undefined
programId: string | undefined
mangoGroup: string | undefined
maxMangoAccounts: number
}
export interface MangoMakeChangeReferralFeeParams {
governedAccount: AssetAccount | undefined
programId: string | undefined
mangoGroup: string | undefined
refSurchargeCentibps: number
refShareCentibps: number
refMngoRequired: number
}
export interface MangoMakeChangeReferralFeeParams2 {
governedAccount: AssetAccount | undefined
programId: string | undefined
mangoGroup: string | undefined
refSurchargeCentibps: number
refShareCentibps: number
refMngoRequired: number
refSurchargeCentibps2: number
refShareCentibps2: number
refMngoRequired2: number
}
/* PsyOptions American options */
export interface PsyFinanceMintAmericanOptionsForm {
contractSize: number
@ -650,20 +486,6 @@ export enum Instructions {
SetMintAuthority,
}
export type createParams = [
rpc: RpcContext,
realm: PublicKey,
governance: PublicKey,
tokenOwnerRecord: PublicKey,
name: string,
descriptionLink: string,
governingTokenMint: PublicKey,
holdUpTime: number,
proposalIndex: number,
instructionsData: InstructionData[],
isDraft: boolean
]
export interface ComponentInstructionData {
governedAccount?: ProgramAccount<Governance> | undefined
getInstruction?: () => Promise<UiInstruction>

View File

@ -36,7 +36,7 @@ const supportedPlugins = [
...gatewayPluginsPks,
]
export const getValidateAccount = async (
const getValidateAccount = async (
connection: Connection,
pubKey: PublicKey
) => {
@ -57,7 +57,7 @@ export const getValidatedPublickKey = (val: string) => {
}
}
export const validateDoseTokenAccountMatchMint = (
const validateDoseTokenAccountMatchMint = (
tokenAccount: AccountInfo,
mint: PublicKey
) => {
@ -94,7 +94,7 @@ export const isExistingTokenAccount = async (
return isExistingTokenAccount
}
export const validateDestinationAccAddress = async (
const validateDestinationAccAddress = async (
connection: ConnectionContext,
val: any,
governedAccount?: PublicKey
@ -122,7 +122,7 @@ export const validateDestinationAccAddress = async (
return true
}
export const validateDestinationAccAddressWithMint = async (
const validateDestinationAccAddressWithMint = async (
connection: ConnectionContext,
val: any,
mintPubKey: PublicKey

View File

@ -7307,7 +7307,7 @@ bigint-buffer@^1.1.5:
dependencies:
bindings "^1.3.0"
bignumber.js@9.0.2, bignumber.js@^8.1.1, bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.0.2, bignumber.js@^9.1.0, bignumber.js@^9.1.1:
bignumber.js@9.0.2, bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.0.2, bignumber.js@^9.1.0, bignumber.js@^9.1.1:
version "9.0.2"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673"
integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==
@ -13887,13 +13887,6 @@ number-to-bn@1.7.0:
bn.js "4.11.6"
strip-hex-prefix "1.0.0"
numbro@2.3.6:
version "2.3.6"
resolved "https://registry.yarnpkg.com/numbro/-/numbro-2.3.6.tgz#4bd622ebe59ccbc49dad365c5b9eed200781fa21"
integrity sha512-pxpoTT3hVxQGaOA2RTzXR/muonQNd1K1HPJbWo7QOmxPwiPmoFCFfsG9XXgW3uqjyzezJ0P9IvCPDXUtJexjwg==
dependencies:
bignumber.js "^8.1.1"
nwsapi@^2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0"